Spring事務傳播屬性介紹(三).Nested
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.