事务注解放到类上面 下面私有方法有效吗_Spring声明式事务,你用对了吗

Spring为不同的事务API实现了统一的编程模型,例如: JTA、JDBC、Hibernate、JPA等。 而如果使用了声明式事务支持,则使用起来更加简洁,只需要要对应的service方法上加上@Transactional注释,即可开启事务支持。 然而正是这种几近于傻瓜化的操作,使得大多数人不再关注事务是否有效,出错时是否按预期正确回滚,反正所有service统统加上事务注解就完事了。 而事务的问题在测试时是不容易被发现的,直到生产环境跑过一段时间,或数据量上来的时候,才发现业务数据掺杂了大量脏数据时,就不得不人工进行数据清洗了。 回想第一次踩事务的坑的时候是2010年,那会刚毕业,对事务一知半解,并且那会也没这么幸福,用的是xml配置事务拦截器,然后方法名必须按特定规则才能被事务拦截器拦截到。然后就踩了不少坑,这里特别感谢下华仔的事务启蒙。所以在这里分享一下这几年在事务上遇到的一些坑及解决方案。 你认为的事务,也许并没有生效 加了@Transactional注解后,事务就一定有效吗? 这里直接列出失效情况,原理后面再分析。 事务注解在非public方法上

如下面这段代码:

public void insertEntity(Test entity) {
        this.saveEntity(entity);}@Transactionalprivate Test saveEntity(Test entity) {
        demoRepository.save(entity);    throw new NullPointerException("test only");}

当然了,这个是比较低级的错误了,相信除非手误,不然一般不会犯这个错。特别是,如果你使用IDEA,直接会提示出错误信息给你,并且给你了修复建议:

62893c04a5ba6c9e6409dd70b9fff526.png

事务方法被内部调用

于是,我们按照提示修复,给方法声明成public,再来试一次:

public void insertEntity(Test entity) {
         this.saveEntity(entity);}@Transactionalpublic Test saveEntity(Test entity) {
         demoRepository.save(entity);    throw new NullPointerException("test only");}

然而,很遗憾,一边异常抛得很开心,另一边数据库也写得很开心。方法明明加了事务注解,方法里明明抛了异常,可是,事务就是没生效。

BUT WHY?

Spring事务使用的是AOP方式对业务方法做了增强,如下图所示:(来自Spring官网)

b9ed5ef7dade3ad687b3d2f57888199a.png

而AOP实现是使用了动态代理,所以必须是从代理方法调用才拥有事务增强的能力,走内部方法,事务自然就失效了。同时也解释了,为什么不能注解在private方法上,还是因为动态代理啊,private是无法被代理到的。以下来自Spring官方文档说明

Due to the p

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值