Spring事务失效的几种场景及原因
spring事务的原理是AOP,进行了切面增强,那么失效的根本原因是这个AOP不起作用了,常见情况如下:
- 抛出检查异常导致事务不能正确回滚
spring事务默认只对非检查异常进行回滚,即运行时异常。检查异常就是程序编译时必须处理的。
解决办法:可以通过配置@Transcational的属性rollbackFor来解决,将rollbackFor设置为Exception.class,即对所以异常都进行回滚。 - 业务方法内通过try-catch将异常捕获后没有再抛出,导致spring事务通知不能捕捉到异常,也就不能进行后面的回滚操作。
解决办法:- 在catch中继续将异常抛出。
- 在catch中手动设置事务回滚
TransactionInterceptor.currentTransactionStatus().setRollbackOnly();
- aop切面顺序导致事务不能回滚
正常情况事务切面的优先级是最低的,是包围在目标方法外的。
自定义切面的优先级也是最低的,和事务切面一样,如果没有指定自定义切面的顺序,那么它会在事务切面的内层,它包围着目标方法,这样目标方法抛出异常后首先被自定义切面捕获到,外层的事务切面的不知道的,如果自定义切面捕获到异常后没有继续抛出,那么事务就不能正确回滚。
解决办法:同情况2 - 非public方法导致的事务失效
@Transcational注解加在public方法上才会生效
Spring为方法创建代理、添加事务通知,前提条件都是该方法是public的 - 调用本类方法导致传播行为失效
调用本类方法是不经过代理的,因此无法增强
解决办法:- 依赖注入自己(代理)来调用
- 通过AppContext拿到代理对象来调用
- @Transcational方法导致的synchronized失效
synchronized保证的仅是目标方法的原子性,环绕目标方法的还有commit等操作,它们并未处一起sync块内
解决办法:synchronized范围扩大至代理方法调用
使用select ... fro update 替换 select - @Transcational没有保证原子行为
事务的原子性仅涵盖insert,update,delete,select ... for update语句,select方法并不阻塞
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤