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

·使用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的配置文件)如下:(我是使用注解方式配置)

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

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

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

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


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

<property name="hibernate.current_session_context_class">org.springframework.orm.hibernate5.SpringSessionContext</property>
然后也可以完美运行

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

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

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


分析

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

<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的事务)。即改成这样:

<property name="hibernate.current_session_context_class">org.springframework.orm.hibernate5.SpringSessionContext</property>


再次深入:

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


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

  • 24
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值