spring事务失效
遇到的问题
前端时间我在做一个父子事务嵌套的时候,出现了子事务失效。在同类的子事务上加事务注解一直都不能创建事务,后来发现是子事务失效了。下面总结一下事务失效情况和解决经验
事务失效有如下几种情况:
- 没有Transaction注解
- 事务没有抛出RuntimeException异常到方法上
- 方法内抛出RuntimenException的父类异常,也就是Error、Exception等
- 同类方法中相互调用,事务失效
- final关键词修饰方法
- 非public关键词修饰方法
造成这么多种类的事务失效的主要原因是spring的动态代理,原因如下:
-
动态代理方法的异常抓取
默认只抓取RuntimeException,所以发生异常前的执行的crud操作还是会被提交的
可以通过@Transaction 的 roolbackfor属性来指定其他异常
-
哪些方法能被动态代理
spring的aop代理,只能代理public访问级别的方法,其中final等关键修饰的方法是不能被代理的。
-
怎么调用代理的方法
spring的aop代理机制,同类的方法之间调用,调用的方法是不会被代理的。比如A类调用B类方法(其中B的方法带有增强的注解),B类中被调用的方法会被代理并增强。但是在B类增强的方法直接调用B类的其他方法(同样方法带有增强的注解),此方法将不会被增强。
可以通过(B)AopContext.currentProxy()来解决此问题,该操作会拿到当前代理类,然后就可以调用想调用的方法。
事务失效解决流程
结合此次经验,事务失效总结分为一下三部
- 检查方法关键字,判断方法是否被代理
- 在方法上打断点 执行TransactionAspectSupport.currentTransactionStatus(),获取当前方法的事务状态,没有事务将会抛出异常。判断父子事务,只用判断对象是不是一个,也就是地址是不是相同。
- 当上面可以获得事务对象,说明当前存在事务,通过事务对象地址来判断是哪里不存在事务,父子方法调用,子方法没有注解,父类有,事务还是会公用的。所以我们一步步排除还是容易查找出来。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了