Spring事务失效的常见情况
Spring事务管理在某些情况下可能会失效,以下是主要的失效场景:
1. 非public方法
- 原因:Spring事务基于AOP实现,默认使用JDK动态代理,只能对public方法进行代理
- 解决方案:将方法改为public或使用AspectJ编译时织入
2. 自调用问题
- 原因:类内部方法调用(如this.method())不会经过代理对象
public class Service {
public void methodA() {
this.methodB(); // 事务失效
}
@Transactional
public void methodB() {
// ...
}
}
- 解决方案:
- 将methodB移到另一个类
- 通过ApplicationContext获取代理对象调用
- 使用AspectJ
3. 异常处理不当
- 原因:
- 捕获了异常未重新抛出
- 抛出的异常不是RuntimeException或Error
- @Transactional未指定rollbackFor
@Transactional
public void method() {
try {
// 可能抛出异常的代码
} catch (Exception e) {
// 捕获异常不抛出,事务不会回滚
}
}
- 解决方案:
- 正确配置rollbackFor
- 需要捕获异常时手动回滚:
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
4. 数据库引擎不支持
- 原因:如MySQL使用MyISAM引擎(不支持事务)
- 解决方案:改用InnoDB引擎
5. 传播行为配置不当
- 原因:如使用PROPAGATION_NOT_SUPPORTED会挂起当前事务
- 解决方案:根据业务需求选择合适的传播行为
6. 多数据源未正确配置
- 原因:多数据源环境下未指定事务管理器
- 解决方案:使用@Transactional注解指定transactionManager
7. 方法final/static
- 原因:final/static方法不能被代理
- 解决方案:避免在事务方法上使用final/static
8. 异步方法
- 原因:@Async方法会在新线程中执行,与原事务不在同一线程
- 解决方案:将异步调用后的操作也纳入事务管理
9. 事务超时
- 原因:事务执行时间超过@Transactional(timeout=…)设置
- 解决方案:优化长时间事务或调整超时时间
10. 嵌套事务传播行为理解错误
- 原因:对PROPAGATION_NESTED等传播行为理解不准确
- 解决方案:深入理解各种传播行为的工作机制
正确使用Spring事务需要理解其底层原理,并注意这些常见的陷阱。

1463

被折叠的 条评论
为什么被折叠?



