Required、Required_New傳播屬性分析傳送門:https://www.cnblogs.com/lvbinbin2yujie/p/10259897.html
Mandatory、Never、Not_Support傳播屬性分析傳送門:https://www.cnblogs.com/lvbinbin2yujie/p/10260030.html
我的Spring事務傳播屬性介紹比較傳送門:https://files.cnblogs.com/files/lvbinbin2yujie/Spring_Tx_Note.rar
Spring事務傳播屬性Nested
說明:如果有事務運行,就作為這個事務的嵌套事務運行; 如果沒有事務運行,新建一個事務運行;
首先要說的,Nested類型事務測試時候使用DataSourceTransactionManager作為事務管理器,DataSourceTransactionManager只對jdbcTemplate、ibatis有效;且需要支持JDBC3.0才起作用
ServiceA.java文件
ServiceB.java文件
ServiceA中的testNest方法本身是個事務;testNest操作了jdbcTemplate寫入一條數據,另外ServiceB的三個NESTED方法分別寫入一條記錄,不過最后一個方法手動模擬拋出了異常;
測試Main方法:
執行之后查看數據庫結果: serviceBNest3方法一定寫入過青雉,但是回滾了記錄;最終testNest方法也成功提交了; 注意的是, 三個Nested方法一定要try-catch,不然testNest的記錄都會回滾,Nested方法也沒意義了; try-catch包圍住NESTED方法,是為了保證NESTED方法執行失敗不干擾到該方法以外執行的操作的正常提交回滾 ; 每一個NESTED方法開始可以看做是一個SavePoint點,執行失敗,就會回滾到該方法開始的地方;
修改下ServiceA.java文件
執行測試方法: 發現數據庫一條記錄都不存在;
原因分析: 外層事務回滾,內層嵌套事務會全部回滾;
NESTED和REQUIRED_NEW的區別:
- 假設都是在一個REQUIRED類型的事務里調用這些事務,就像上面的例子,該REQUIRED類型方法調用拋出異常,REQUIRED_NEW的方法仍然可以提交,但是NESTED還要受到REQUIRED事務回滾而被迫回滾; 這就是我認為的新的事務與內嵌事務的區別;
- 假設都是在一個REQUIRED類型的事務里調用這些事務方法,REQUIRED_NEW和NESTED都拋出異常的情況下,外層事務不寫try-catch,都會導致該REQUIRED類型事務全部回滾. REQUIRED_NEW和NESTED調用處寫了try-catch塊,外層可以正常提交 ; 但是REQUIRED類型的外層即使寫了Try-catch塊,也會拋出異常: Transaction rolled back because it has been marked as rollback-only
查看源碼的時候,又意識到一個問題:
ServiceA.java文件
ServiceB.java文件
說明: 當全局事務ReadOly為true的時候,ServiceB的方法為NESTED類型,即使ServiceB不執行數據庫增刪改操作,同樣會拋出異常;
Connection is read-only. Queries leading to data modification are not allowed.
原因分析:因為NESTED事務是采用JDBC3.0的SavePoint進行回滾事務,只讀的Connection創建回滾點就會拋出該異常;關於該異常具體信息我也不甚了解。同樣的,只讀事務即使不使用NESTED事務,如果進行增刪改操作,也會拋出異常
Connection is read-only. Queries leading to data modification are not allowed.