Spring坑系列——Spring事务注解Transactional失效

  • A+
所属分类:Java 程海无涯

前情提要:当Service接口实现类中存在内部方法调用,并且方法需要支持事务控制时,事务控制失效,事务的传播级别为默认Required(默认模式)。

1、简化版翻车代码:

Spring坑系列——Spring事务注解Transactional失效
Service接口层

Spring坑系列——Spring事务注解Transactional失效
Service接口实现类

2、需求说明:

(1)数据库表主要有两个,t_user(用户表),t_sms(发送短信记录表);

(2)主业务为新用户注册,往数据库中添加用户记录,t_user表中有记录存在,后面的其他操作不应该影响此操作(方法有事务);

(3)辅助功能(方法有事务),先往t_sms表中记录短信内容,再调API网关服务,向用户发送注册成功短信提醒,如果API网关服务调用成功,则t_sms表中有记录,如查API网关服务调用失败,则t_sms表中无记录(事务回滚)

3、结果:

当辅助功能方法发生异常时,该方法的事务控制失效,两张表中都会有记录存在,没达到预期的效果。

4、@Transactional失效原因分析:

在应用系统调用声明@Transactional 的目标方法时,Spring Framework 默认使用 AOP 代理,在代码运行时生成一个代理对象,再由这个代理对象来统一管理,当在Service实现类直接调用内部方法时,其本质是通过this对象来调用的方法,而不是代理对象,因为会出现事务失效的情况

5、解决方法:

内部调用是没有事务的,事务的原理就是aop实现。自己new的对象spring也不会管理事务。

1.显示的通过代理对象来调用方法1.显示的通过代理对象来调用方法:

Spring坑系列——Spring事务注解Transactional失效

如果如上操作还生效,则在在Spring配置文件中加入

<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>

暴露代理对象,同时引入aspectj 和cglib相关jar包

2.可以试试把自己注入到自己里面

6、总结——注解方式的事务使用注意事项:

(1)正确的设置@Transactional 的 propagation 属性

(2)正确的设置@Transactional 的 rollbackFor 属性

(3)@Transactional 只能应用到 public 方法才有效

(4)遇到方法自调用问题,显示通代理对象调用

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: