Spring @Transactional搭配Hibernate报错:无活动事务时saveOrUpdate无效
Spring @Transactional 生效逻辑与失效解决方案
核心生效逻辑
Spring的@Transactional基于AOP动态代理实现:当你调用被Spring管理的Bean中标记了@Transactional的public方法时,事务切面会自动拦截本次调用,在方法执行前开启事务,方法正常执行完成后提交事务,方法抛出未捕获的回滚异常(默认是RuntimeException和Error)时自动回滚事务,全程自动处理Session获取、资源释放逻辑,不需要手动编码处理。
异常根因排查
你遇到的Calling method 'saveOrUpdate' is not valid without an active transaction异常,本质是@Transactional注解根本没有生效,Spring没有自动为你开启事务,所以调用Hibernate的API时才会提示没有活跃事务。你已经配置了SessionFactory和HibernateTransactionManager,大概率是漏掉了以下关键配置或使用姿势错误:
- 没有开启事务注解驱动:XML配置模式下需要在配置文件中添加
<tx:annotation-driven transaction-manager="txManager"/>,注解配置模式下需要在配置类上添加@EnableTransactionManagement注解,这是让@Transactional生效的核心开关,很多开发者都会遗漏这一步。 - 导错了注解包:确认你使用的@Transactional是
org.springframework.transaction.annotation.Transactional,而不是javax包下的javax.transaction.Transactional,Spring默认只会识别自己包下的事务注解。 - 方法调用不符合代理规则:如果你是在DaoImpl类的内部方法中直接调用
saveOrUpdateOne,走的是this调用而非Spring代理对象的调用,会跳过事务切面,注解自然不生效。这种情况需要把事务注解加在外部调用的入口public方法上,或者从Spring上下文中获取Dao的代理对象再调用该方法。 - 方法不是public修饰:@Transactional仅对public方法生效,非public方法即使加了注解也不会被事务切面拦截。
手动事务代码的说明
你修改后的手动处理事务的代码能正常运行,是因为你完全绕开了Spring的事务管理机制,自己编码完成了事务开启、提交、回滚、资源释放的全流程,本质上没有用到@Transactional的能力,属于冗余实现。
你最开始写的简化版代码本身没有问题,只要修正上面提到的配置或使用问题,就能正常运行,不需要额外编写事务处理逻辑。
内容的提问来源于stack exchange,提问作者Steve Atkinson
相关产品推荐
相关产品推荐

