spring和hibernate整合时异常(详解): getFlushMode is not valid without active transaction

来源:互联网 发布:关联数组和索引数组 编辑:程序博客网 时间:2024/05/19 10:39

本文是转载文章,文章的来源:CSDN博客

博主:maoyuanming0806

文章:springhibernate整合时异常(详解): getFlushMode is not valid without active transaction

博文地址:

http://blog.csdn.net/maoyuanming0806/article/details/61417995



·使用spring和hibernate整合+struts2整合时,服务器启动没问题,访问action时报错:

HTTP Status 500 - getFlushMode is not valid without active transaction; nested exception is org.hibernate.HibernateException: getFlushMode is not valid without active transaction


首先查看自己有没有配置开启事务


首先bean.xml(spring的配置文件)如下:(我是使用注解方式配置)

[html] view plain copy
  1. <!-- 配置事务一 配置事务管理器 -->  
  2. <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">  
  3.     <!-- 指明事务使用在哪个数据源,class也有该属性的声明  
  4.         此处可以配置sessionFactory属性,因为它的对象已经配置注入了dataSource  
  5.      -->  
  6.     <property name="sessionFactory" ref="sessionFactory"></property>  
  7. </bean>  
  8.   
  9. <!-- 配置事务二 开启事务注解 -->  
  10. <tx:annotation-driven transaction-manager="transactionManager"/>  
然后service上加注解:
[java] view plain copy
  1. @Transactional  
  2. public class UserService {  
  3.     private UserDao userDao;  
  4.     public void setUserDao(UserDao userDao) {  
  5.         this.userDao = userDao;  
  6.     }  
  7.     public void add(){  
  8.         System.out.println("service.......");  
  9.         userDao.add();    
  10.     }     
  11. }  

如上,我都开启了事务,还是出错。查资料查配置文件发现这一条:hibernate.cfg.xml文件中:

[html] view plain copy
  1. <property name="hibernate.current_session_context_class">thread</property>  
就是这个问题,先说一下解决方法:两种方法:

第一种:hibernate3.x及以上的版本可以直接注释掉这条代码,或者删除也行   然后测试,可以完美运行了


第二种:标签值thread改成 : org.springframework.orm.hibernate5.SpringSessionContext     (因为我的hibernate是5.x的版本)最后改成:

[html] view plain copy
  1. <property name="hibernate.current_session_context_class">org.springframework.orm.hibernate5.SpringSessionContext</property>  
然后也可以完美运行

注意注意:如果修改了以后还是不能够解决这个问题,就是说还是会报那个错误,那么,服务器缓存清一下,浏览器缓存清一下

还没解决的话那就把项目运行环境改一下:如下改--》鼠标在项目上右击选择properties:

这可能是因为myeclipse环境跑飞的原因吧,它没有把最新的项目文件更新到tomcat的运行目录或者说虚拟目录下。那么我们可以手动把项目从服务器删除,然后重新部署


分析

然后,我们来看出这个错误修改的具体原因和思路

[html] view plain copy
  1. <property name="hibernate.current_session_context_class">thread</property>  

首先看这段代码的用处:

让我们在某一个上下文环境(比如说当前线程)中可通过SessionFactory.getCurrentSession()得到同一个session

我们所知道的是,hibernate中事务是需要在dao执行sql相关语句时来手动开启的,然后底层实现代码时由getCurrentSession得到的session中可以得到transaction,所以可以正常运行

错误原因:

而spring中事务是在配置文件中配置自动开启,因为由getCurrentSession得到的session中是当前线程的session,但是当前线程中没有开启事务的代码,所以不能获transaction  。然而spring+hibernate整合必须要有活动的事务才能执行dao中的方法,这个可以从报错信息中可以看出。

解决思路:

因为我们把sessionFactory的产生放在spring配置文件中,即让服务器启动时就创建这个对象,这样的话它就被存在一个上下文环境中,即在SpringSessionContext中保存
所以我们要把绑定当前线程session改成绑定这个spring上下文环境,即设置为由spring环境管理(因为事务aop也是在spring中),这时spring中的事务配置才会起作用(当然,以前是thread上下文环境的session,而事务托管在spring上下文中,当然spring无法管理到thread上下文的session的事务)。即改成这样:

[html] view plain copy
  1. <span style="font-size:12px;"><property name="hibernate.current_session_context_class">org.springframework.orm.hibernate5.SpringSessionContext</property></span>  


再次深入:

我们查看ThreadLocalSessionContext,JTASessionContext,ManagedSessionContext,SpringSessionContext这几个类定义发现,都实现了一个接口org.hibernate.context.spi.CurrentSessionContext它定义了单一的方法currentSession(),特定的实现用它来负责跟踪当前的上下文相关的会话。那么,线程绑定或是上下文绑定,最后都是使用实现了CurrentSessionContext接口的一个类,来跟踪session,然后我们通过这个类的对象来获得被它跟踪的session,以达到在我们定义的上下文环境中调用getCurrentSession方法获得的总是同一个session


 查了很多资料得出的一些经验之谈,若有叙述不当之处,私信与我立即改正,谢谢

阅读全文
0 0
原创粉丝点击