springboot事务方法间调用

非事务外围方法调用同类的事务方法,内部方法抛异常,外部方法捕获异常。结果,内外方法都能插入数据。结果猜想:事务给了外部方法,外部方法捕获了异常,导致外部方法没有察觉到异常,虽然内部方法察觉到异常,但事务由外部方法决定。最后结果就是内外方法都插入数据。

为了验证猜想,我把之前内部方法的事务取消,并给原本没有事务的外部方法添加事务,看看结果是不是一样,如果一样,那就说明,只要是同一个类,不管事务注解标注在内部方法还是外部方法,最后都给外部方法,而内部方法事务失效(Aop导致)。

结果:和上一实验一样。证明了猜想。结论:同类的方法调用,事务给外围方法,内部方法事务失效(内部方法抛异常,内部方法也不会回滚)

 

如果把异常捕获放到内部如何呢?

同时数据库也有数据。

结果是一样:外部方法依然没有感受到异常,所以不会回滚,内部方法也没有感受到异常(即使感受结果也是一样),所以最后结果是都插入数据。

上面的结果都是两个都插入数据,有没有一个插入一个不插入的呢?答案是不存在,原因看后文结论

结果是内外都不插入。此时说明了,同一个类的方法调用,只要外部事务感受到异常,内外都会回滚。外部事务没有感受到异常,都不会回滚。自己领悟了一个好理解的统一方法:就是把内部方法的代码作为外部方法的一部分看待,一切迎然而解。

数据库内外方法都有数据。

结论一:同一个类的方法调用,外围方法和内围方法其中一个有事务注解或者两者都有注解,则注解给外部方法,内部方法则看成外部方法的一部分,只要外部方法感受不到异常(内外方法都未抛异常、内部抛出但内部或外部捕获、外部抛出外部捕获)都不会回滚,只要外部方法感受到异常(内部或外部抛出,但未捕获),内外方法都会回滚。同一个类的方法调用,如果两者都没有事务注解,则没有事务,此时,无论如何都不可能存在回滚的情况。

 

数据库有数据。

修改doB1():数据库没数据

修改doB1():数据库没数据

 

在外部方法捕获异常 

数据库内外方法都有数据

给doB1添加事务,结果数据库没数据。

 

接下来不测了,直接写结论:

结论二:不同类的方法调用。外部方法调用不同类的内部方法,外部方法有事务时,分为两种情况:1、内部方法无事务。此时之只要把内部方法看成外部方法的一部分就可以了。只要外部方法感受不到异常(内外都不抛异常、内抛内捕获、内抛外捕获、外抛外捕获),就不会回滚。只要感受到异常就会回滚(内抛或外抛,但均不捕获)。2、内部方法有事务,则内部方法共用同一事物,与内部方法没有事务的区别是,内部方法有事务只要内部方法感受到异常,就会回滚,并且导致外部方法也回滚,即使外部方法捕获了内部方法抛出的异常。

结论总结:

一、同一个类的方法调用,外围方法和内围方法其中一个有事务注解或者两者都有注解,则注解给外部方法,内部方法则看成外部方法的一部分,只要外部方法感受不到异常(内外方法都未抛异常、内部抛出但内部或外部捕获、外部抛出外部捕获)都不会回滚,只要外部方法感受到异常(内部或外部抛出,但未捕获),内外方法都会回滚。同一个类的方法调用,如果两者都没有事务注解,则没有事务,此时,无论如何都不可能存在回滚的情况。

二、不同类的方法调用。外部方法调用不同类的内部方法,外部方法有事务时,分为两种情况:1、内部方法无事务。此时之只要把内部方法看成外部方法的一部分就可以了。只要外部方法感受不到异常(内外都不抛异常、内抛内捕获、内抛外捕获、外抛外捕获),就不会回滚。只要感受到异常就会回滚(内抛或外抛,但均不捕获)。2、内部方法有事务,则内部方法共用同一事物,与内部方法没有事务的区别是,内部方法有事务只要内部方法感受到异常,就会回滚,并且导致外部方法也回滚,即使外部方法捕获了内部方法抛出的异常。

最后说明:以上的分析均是基于默认的传播行为-REQUIRED,可以看到仅仅分析其中一种传播行为,所有情况加起来估计就有几十种,所以远没有网上其他文章随便测几个就得出结论那么简单。要考虑的情况1.是同一类的方法调用还是不同类的方法调用?2、内部方法是否有事务?3.外部方法是否有事务?4、内部方法是否抛异常?5、外部方法是否抛异常?6、内部方法抛异常是否捕获?7外部方法抛异常是否捕获?8、由内部方法捕获还是外部方法捕获?。。。。。光这8个情况就有共有64种情况。

 

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Spring Boot是一个开源的Java web框架,它提供了很多便利的特性和工具,其中包括事务管理。Spring Boot的事务管理可以通过@Transactional注解来实现。在使用@Transactional注解时,如果方法中发生异常,该方法中对数据库的所有操作将被回滚。如果没有异常发生,则事务将被提交。同时,可以在方法调用前使用@Transaction注解来设置事务的传播行为(Propagation)和隔离级别(Isolation)。传播行为指的是当前方法与另一个事务交互时,如何处理事务,例如是否加入已有的事务、是否创建新的事务等等。隔离级别指的是多个事务的隔离程度,例如是否能够读取到未提交的数据等等。 下面是一个使用@Transactional注解实现事务管理的示例: ``` @Service public class UserServiceImpl implements UserService { @Autowired private UserRepository userRepository; @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT) public void saveUser(User user) { userRepository.save(user); } @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT) public void updateUser(User user) { userRepository.save(user); } @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT) public void deleteUser(Long userId) { userRepository.deleteById(userId); } } ``` 在上面的示例中,我们使用了@Transactional注解来标记三个方法。这三个方法都使用了默认的传播行为和隔离级别。如果这些方法中任何一个出现异常,则所有对数据库的操作都将被回滚。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值