Spring中NESTED和REQUIRED_NEW傳播行為的區別


簡介

PROPAGATION_REQUIRED_NEW:
表示當前方法必須運行在它自己的事務中。一個新的事務將被啟動。如果存在當前事務,在該方法執行期間,當前事務會被掛起。如果使用JTATransactionManager的話,則需要訪問TransactionManager。
PROPAGATION_NESTED:
表示如果當前已經存在一個事務,那么該方法將會在嵌套事務中運行。嵌套的事務可以獨立於當前事務進行單獨地提交或回滾。如果當前事務不存在,那么其行為與PROPAGATION_REQUIRED一樣。注意各廠商對這種傳播行為的支持是有所差異的。可以參考資源管理器的文檔來確認它們是否支持嵌套事務。
嵌套事務: 外事物異常,內事物回滾;內事物異常,外事物正常。

案例

PROPAGATION_REQUIRED_NEW案例

serviceOne層中方法

@Transactional(rollbackFor = Exception.class)
    public void  moneyTestREQUIRED_NEWOne(){
        log.info("moneyTestREQUIRED_NEWOne事物名字{}", TransactionSynchronizationManager.getCurrentTransactionName());
        //1.查詢病人基本信息
        List<TBICXX> tbicxx = basisDao.getTBICXX();
        //2.根據CMZH更新TBMZFYHZ
        Integer TBMZFYHZCount = tbmzfyhzDao.updateByCMZH("土登", "1903003643");
        log.info("更新TBMZFYHZ影響行數{}",TBMZFYHZCount);
        try {
            propagationBehaviorTwo.moneyTestREQUIRED_NEWTwo();
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("-------------事物雖然回滾了,但是邏輯繼續執行------------");
    }

serviceTwo層中方法

@Transactional(rollbackFor = Exception.class,propagation= Propagation.REQUIRES_NEW)
    public void  moneyTestREQUIRED_NEWTwo(){
        log.info("moneyTestREQUIRED_NEWTwo事物名字{}", TransactionSynchronizationManager.getCurrentTransactionName());
        //3.根據CMZH更新TBMZFYMXGH
        Integer integer = tbmzfymxghDao.updateByCMZH("土登", "2107000224");
        log.info("更新TBMZFYMXGH影響行數{}",integer);
        int i=2/0;
    }

Test層中方法

  /**
     *  測試其傳播行為
     *   PROPAGATION_REQUIRED_NEW:
     *       表示當前方法必須運行在它自己的事務中。一個新的事務將被啟動。如果存在當前事務,在該方法執行期間,當前事務會被掛起。如果使用JTATransactionManager的話,則需要訪問TransactionManager
     *
     **/
    @Test
    public void testTransationalPropagationREQUIRED_NEW(){
        behaviorOne.moneyTestREQUIRED_NEWOne();
    }

運行前
image
運行后數據庫數據
image
運行后控制台打印
image
結論
外事物和內事物是獨立的事物,內事物異常回滾不影響外事物,外事物回滾不影響內事物。

PROPAGATION_NESTED案例

serviceOne層中方法

@Transactional(rollbackFor = Exception.class)
    public void  moneyTestNESTEDOne(){
        log.info("moneyTestNESTEDOne事物名字{}", TransactionSynchronizationManager.getCurrentTransactionName());
        //1.查詢病人基本信息
        List<TBICXX> tbicxx = basisDao.getTBICXX();
        //2.根據CMZH更新TBMZFYHZ
        Integer TBMZFYHZCount = tbmzfyhzDao.updateByCMZH("三筒", "1903003643");
        log.info("更新TBMZFYHZ影響行數{}",TBMZFYHZCount);
        try {
            propagationBehaviorTwo.moneyTestNESTEDTwo();
        } catch (Exception e) {
            // 為了避免 org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only 該異常產生
            // TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            e.printStackTrace();
        }
        int i=2/0;  //JJ句
        log.info("-------------事物雖然回滾了,但是邏輯繼續執行------------");
    }

serviceTwo層中方法

@Transactional(rollbackFor = Exception.class,propagation= Propagation.NESTED)
    public void  moneyTestNESTEDTwo(){
        log.info("moneyTestNESTEDTwo事物名字{}", TransactionSynchronizationManager.getCurrentTransactionName());
        //3.根據CMZH更新TBMZFYMXGH
        Integer integer = tbmzfymxghDao.updateByCMZH("三筒", "2107000224");
        log.info("更新TBMZFYMXGH影響行數{}",integer);
		int i=2/0;   //KK句
    }

運行前數據庫數據
image
--------------KK句注釋調運行結果,JJ句開啟---------------
運行后數據庫數據
image
運行后控制台打印
image
--------------JJ句注釋調運行結果,KK句開啟---------------
運行后數據庫數據
image

運行后控制台打印
image
結論
嵌套事物: 運行的是同一個事物,外事物提交,內事物回滾是通過設置回滾點來實現,具體實現過程參考:
https://www.jianshu.com/p/2f79ee33c8ad

Gitee代碼地址

https://gitee.com/zhuayng/foundation-study/tree/develop/SpringBootDemo/src/main/java/com/yxkj/springbootdemo/service/impl


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM