Spring集成Hibernate5_01-basic

来源:互联网 发布:天音淘宝宝贝复制软件 编辑:程序博客网 时间:2024/06/02 06:50

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文件位置

    <!-- 设置jdbc.properties文件位置 -->    <context:property-placeholder location="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

原创粉丝点击