您当前的位置: 首页 >  hibernate

宝哥大数据

暂无认证

  • 1浏览

    0关注

    1029博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Spring集成Hibernate5_01-basic

宝哥大数据 发布时间:2017-09-03 16:18:07 ,浏览量:1

1、导入hibernate的包和Spring的包

1.1、导入Spring的依赖包 1.2、导入Log4j的依赖包 1.3、导入dbcp的依赖包 1.4、导入Hibernate3的依赖包(hibernate3.jar,required文件中的所有,slf4j-api.jar,)

2、创建SpringBean.xml 2.1、使用DBCP创建dataSource, 和集成JDBC一样

这里写图片描述

设置jdbc.properties文件位置
    
    
2.2、创建Hibernate的的sessionFactory 2.2.1、首先我们看一下以前的hibernate.cfg.xml配置,创建sessionFactory

这里写图片描述

2.2.2、创建集成hibernate的sessionFactory

官网有介绍19.3.1 SessionFactory setup in a Spring container ,

下面为实际配置

这里写图片描述

3、为实体类创建hibernate的Annotation或者hbm文件

这里写图片描述

4、创建基于Hibernate的Dao 4.1、实现IUserDao
package com.chb.spring_hibernate.dao;

import java.util.List;

import com.chb.spring_hibernate.model.User;

public class UserHibernateDao implements IUserDao{

   ...//实现IUserDao的方法

}
4.2、在相应的Dao中注入相应的SessionFactory

这里写图片描述

4.2.1、如果hibernate自己管理sessionFactory, 就要通过配置文件创建sessionFactory , 然后通过openSession来获取Session.
package com.chb.hbUtils;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtils {
    private static Session session;

    private static SessionFactory getFactory() {
        Configuration config = new Configuration().configure();
        SessionFactory sessionFactory = config.buildSessionFactory();
        return sessionFactory;
    }

    public static Session getSession() {
        if (session == null) {
            session = getFactory().openSession();
        }
        return session;
    } 

    public static  void  close() {
        if (session !=  null) {
            session.close();
        }
    }
}
4.2.2、如果通过Spring来管理相应的SessionFactory,不再使用factory.openSession()开启session,而应该是使用facotry.getCurrentSession来打开Session,这个Session就会被Spring所管理,此时开发人员不用进行事务控制,也不用关闭Session,全部有Spring容器来完成

    /**
     * 获取Session, 
     * 注意: 没有使用openSession(), 而是getCurrentSession()才能被Spring所管理
     * @return
     */
    private Session getSession() {
        return sessionFactory.getCurrentSession();
    }
4.3、为Group创建基于Hibernate的Dao, 同样注入sessionFactory, 通过session来进行相应的操作。
package com.chb.spring_hibernate.dao;

import javax.annotation.Resource;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.chb.spring_hibernate.model.Group;

public class GroupHibernateDao implements IGroupDao{
    //注入sessionFactory
    private SessionFactory sessionFactory;
    //提供相应的getter setter 
    @Resource(name="mySessionFactory")//注入sessionFactory
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    /**
     * 获取Session, 
     * 注意: 没有使用openSession(), 而是getCurrentSession()才能被Spring所管理
     * @return
     */
    private Session getSession() {
        return sessionFactory.getCurrentSession();
    }

    public void addGroup(Group group) {

    }
}
4.4、sessionFactory注入的优化   每多一个实体类, 我们都要注入SessionFactory, 这部分代码功能都是一样的, 我们如果每个Dao中重复写这部分代码就是做重复工作, 我们可以将这部分代码提取出来, 写一个BaseDao类
package com.chb.spring_hibernate.dao;

import javax.annotation.Resource;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

public class BaseDao {
    //注入sessionFactory
    private SessionFactory sessionFactory;
    //提供相应的getter setter 
    @Resource(name="mySessionFactory")//注入sessionFactory
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    /**
     * 获取Session, 
     * 注意: 没有使用openSession(), 而是getCurrentSession()才能被Spring所管理
     * @return
     * //使用protected权限,只有子类可以使用
     */
    protected Session getSession() {
        return sessionFactory.getCurrentSession();
    }



}
这样, GroupHibernateDao, UserHibernateDao 只需要继承BaseDao, 代码就简洁多了。 5、测试: 添加一哥group
package com.chb.spring_hibernate.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.chb.spring_hibernate.dao.GroupHibernateDao;
import com.chb.spring_hibernate.dao.IGroupDao;
import com.chb.spring_hibernate.model.Group;

public class Test {

    @org.junit.Test 
    public void testHibernateAdd(){
        ApplicationContext context = new ClassPathXmlApplicationContext("SpringBean.xml");
        IGroupDao groupDao = context.getBean(GroupHibernateDao.class);
        Group group = new Group();
        group.setGroupName("计算机系");
        groupDao.addGroup(group);
    }
}
报错1、
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userHibernateDao': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mySessionFactory': Failed to introspect bean class [org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean] for lookup method metadata: could not find class that it depends on; nested exception is java.lang.NoClassDefFoundError: [Lorg/hibernate/engine/FilterDefinition;
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.
原因: Spring整合Hibernate 使用注解类出错, 在Hibernate3可以使用AnnotationSessionFactoryBean来创建sessionFactory,但是,Hibernate4已经不支持这个了。Hibernate 只能使用org.springframework.orm.hibernate4.LocalSessionFactoryBean, 那么要怎么配置注解形式的model呢?很简单,因为LocalSessionFactoryBean里面已经整合了annotation,
    public void setPackagesToScan(String... packagesToScan) {
        this.packagesToScan = packagesToScan;
    }
报错2、 原因: 配置Spring事务处理,只有配置了事务处理之后,Spring才能有效的管理事务
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
六、配置Spring事务处理,只有配置了事务处理之后,Spring才能有效的管理事务 参考: 20.4.3 Transaction management

Spring是通过aop来实现事务处理

这里写图片描述

再次执行测试, 继续报错3、java.lang.ClassCastException: com.sun.proxy.$Proxy20 cannot be cast to com.chb.spring_hibernate.dao.UserHibernateDao
java.lang.ClassCastException: com.sun.proxy.$Proxy20 cannot be cast to com.chb.spring_hibernate.dao.UserHibernateDao
    at com.chb.spring_hibernate.test.Test.testHibernateAdd(Test.java:22)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

解决参照: http://blog.csdn.net/danchaofan0534/article/details/53575106 继续报错4、java.lang.ClassNotFoundException: org.hibernate.engine.transaction.spi.TransactionContext 本项目是Spring4 + Hibernate5 , 但是在设置事务管理器时参考的是HIberrnate4的文档,导致出错。

这里写图片描述

报错6、java.lang.IllegalStateException: No value for key [org.hibernate.internal.SessionFactoryImpl@5226e402] bound to thread [main]

我他妈要疯了

java.lang.IllegalStateException: No value for key [org.hibernate.internal.SessionFactoryImpl@5226e402] bound to thread [main]
    at org.springframework.transaction.support.TransactionSynchronizationManager.unbindResource(TransactionSynchronizationManager.java:210)
    at org.springframework.orm.hibernate5.HibernateTransactionManager.doCleanupAfterCompletion(HibernateTransactionManager.java:649)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.cleanupAfterCompletion(AbstractPlatformTransactionManager.java:1017)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:883)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:830)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing(TransactionAspectSupport.java:522)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:286)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
    at com.sun.proxy.$Proxy19.addGroup(Unknown Source)
    at com.chb.spring_hibernate.test.Test.testHibernateAdd(Test.java:19)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

碰巧和上面一样, 在注入sessionFactory时,

这里写图片描述

总算他妈的成功了,

这里写图片描述

测试load GroupHibernateDao中load方法
    public Group load(int id) {
        return getSession().load(Group.class, 1);
    }
测试

    @org.junit.Test 
    public void testLoad(){
        ApplicationContext context = new ClassPathXmlApplicationContext("SpringBean.xml");
        IGroupDao groupDao = (IGroupDao)context.getBean("groupHibernateDao");
        System.out.println(groupDao.load(1));

    }
测试结果: 报错7、org.hibernate.LazyInitializationException: could not initialize proxy - no Session 报错是一个懒加载异常,是在session(hibernate里的session)关闭后使用group对象的未加载变量,也就是说session已经关闭,然而该实例变量却还没有被初始化,就使用了该实例变量,导致该异常。

下面给出三种解决办法,个人认为第二种比较好

1、把lazy设成false。这个是最简单的办法,个人认为也是比较笨的方法。因为这是在用效率作为代价。

2、使用OpenSessionInViewFilter。这种方法是将session交给servlet filter来管理,每当一个请求来之后就会开

启一个session,只有当响应结束后才会关闭。如下:

3、将hibernate的抓起策略改为join。也就是是left join fetch或inner join fetch语法。就是在

我们会在后续中考虑OpenSessionInViewFilter, 本节先不处理, 将load改为get
关注
打赏
1587549273
查看更多评论
立即登录/注册

微信扫码登录

0.0436s