一、描述
Spring遇到嵌套事務時,當被嵌套的事務被定義為“PROPAGATION_REQUIRES_NEW”時,
內層Service的方法被調用時,外層方法的事務被掛起;
內層事務相對於外層事務是完全獨立的,有獨立的隔離性等等。
二、實驗
但實驗時卻遇到一個奇怪的問題:
1、當ServiceA.a()方法調用ServiceB.b()方法時,內層事務提交和回滾,都不受外層事務提交或回滾的影響。
2、當ServiceA.a()方法調用ServiceA.c()方法時,內層事務不能正確地提交或回滾。
三、演示代碼
XXXService中,有下面兩個方法:
@Transactional
method_One() {
method_Two();
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
method_Two(){
//do something
}
四、分析和結論
1、method_Two()會不會創建一個新事務?
答:不會創建。仔細查看了日志,沒有找到類似creating new transaction的輸出,應該是因為在同一個Service類中,spring並不重新創建新事務,如果是兩不同的Service,就會創建新事務了。
那么為什么spring只對跨Service的方法才生效?
Debug代碼發現跨Service調用方法時,都會經過org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor.intercept()方法,只有經過此處,才能對事務進行控制。
2、不同的Service調用方法時:
如果被調用方法是Propagation.REQUIRES_NEW,被catch后不拋出,事務可以正常提交;
如果被調用方法是Propagation.REQUIRED,被catch后不拋出,后面的代碼雖然可以執行下去,但最終還是會分出rollback-only異常;
3、同一個Service中調用方法時:
不論注解是Propagation.REQUIRES_NEW 還是 Propagation.REQUIRED,
其結果都是一樣的,就是都被忽略掉了,等於沒寫。
當其拋出異常時,只需catch住不拋出,事務就可以正常提交。