当前位置:   article > 正文

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

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

如下面这段代码:

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

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

62893c04a5ba6c9e6409dd70b9fff526.png

事务方法被内部调用

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

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

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

BUT WHY?

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

b9ed5ef7dade3ad687b3d2f57888199a.png

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

Due to the p

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/224676
推荐阅读
相关标签
  

闽ICP备14008679号