非事务外围方法调用同类的事务方法,内部方法抛异常,外部方法捕获异常。结果,内外方法都能插入数据。结果猜想:事务给了外部方法,外部方法捕获了异常,导致外部方法没有察觉到异常,虽然内部方法察觉到异常,但事务由外部方法决定。最后结果就是内外方法都插入数据。
为了验证猜想,我把之前内部方法的事务取消,并给原本没有事务的外部方法添加事务,看看结果是不是一样,如果一样,那就说明,只要是同一个类,不管事务注解标注在内部方法还是外部方法,最后都给外部方法,而内部方法事务失效(Aop导致)。
结果:和上一实验一样。证明了猜想。结论:同类的方法调用,事务给外围方法,内部方法事务失效(内部方法抛异常,内部方法也不会回滚)
如果把异常捕获放到内部如何呢?
同时数据库也有数据。
结果是一样:外部方法依然没有感受到异常,所以不会回滚,内部方法也没有感受到异常(即使感受结果也是一样),所以最后结果是都插入数据。
上面的结果都是两个都插入数据,有没有一个插入一个不插入的呢?答案是不存在,原因看后文结论
结果是内外都不插入。此时说明了,同一个类的方法调用,只要外部事务感受到异常,内外都会回滚。外部事务没有感受到异常,都不会回滚。自己领悟了一个好理解的统一方法:就是把内部方法的代码作为外部方法的一部分看待,一切迎然而解。
数据库内外方法都有数据。
结论一:同一个类的方法调用,外围方法和内围方法其中一个有事务注解或者两者都有注解,则注解给外部方法,内部方法则看成外部方法的一部分,只要外部方法感受不到异常(内外方法都未抛异常、内部抛出但内部或外部捕获、外部抛出外部捕获)都不会回滚,只要外部方法感受到异常(内部或外部抛出,但未捕获),内外方法都会回滚。同一个类的方法调用,如果两者都没有事务注解,则没有事务,此时,无论如何都不可能存在回滚的情况。
数据库有数据。
修改doB1():数据库没数据
修改doB1():数据库没数据
在外部方法捕获异常
数据库内外方法都有数据
给doB1添加事务,结果数据库没数据。
接下来不测了,直接写结论:
结论二:不同类的方法调用。外部方法调用不同类的内部方法,外部方法有事务时,分为两种情况:1、内部方法无事务。此时之只要把内部方法看成外部方法的一部分就可以了。只要外部方法感受不到异常(内外都不抛异常、内抛内捕获、内抛外捕获、外抛外捕获),就不会回滚。只要感受到异常就会回滚(内抛或外抛,但均不捕获)。2、内部方法有事务,则内部方法共用同一事物,与内部方法没有事务的区别是,内部方法有事务只要内部方法感受到异常,就会回滚,并且导致外部方法也回滚,即使外部方法捕获了内部方法抛出的异常。
结论总结:
一、同一个类的方法调用,外围方法和内围方法其中一个有事务注解或者两者都有注解,则注解给外部方法,内部方法则看成外部方法的一部分,只要外部方法感受不到异常(内外方法都未抛异常、内部抛出但内部或外部捕获、外部抛出外部捕获)都不会回滚,只要外部方法感受到异常(内部或外部抛出,但未捕获),内外方法都会回滚。同一个类的方法调用,如果两者都没有事务注解,则没有事务,此时,无论如何都不可能存在回滚的情况。
二、不同类的方法调用。外部方法调用不同类的内部方法,外部方法有事务时,分为两种情况:1、内部方法无事务。此时之只要把内部方法看成外部方法的一部分就可以了。只要外部方法感受不到异常(内外都不抛异常、内抛内捕获、内抛外捕获、外抛外捕获),就不会回滚。只要感受到异常就会回滚(内抛或外抛,但均不捕获)。2、内部方法有事务,则内部方法共用同一事物,与内部方法没有事务的区别是,内部方法有事务只要内部方法感受到异常,就会回滚,并且导致外部方法也回滚,即使外部方法捕获了内部方法抛出的异常。
最后说明:以上的分析均是基于默认的传播行为-REQUIRED,可以看到仅仅分析其中一种传播行为,所有情况加起来估计就有几十种,所以远没有网上其他文章随便测几个就得出结论那么简单。要考虑的情况1.是同一类的方法调用还是不同类的方法调用?2、内部方法是否有事务?3.外部方法是否有事务?4、内部方法是否抛异常?5、外部方法是否抛异常?6、内部方法抛异常是否捕获?7外部方法抛异常是否捕获?8、由内部方法捕获还是外部方法捕获?。。。。。光这8个情况就有共有64种情况。