1. 程式人生 > >Spring事務傳播屬性介紹(三).Nested

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的區別:

  1. 假設都是在一個REQUIRED型別的事務裡呼叫這些事務,就像上面的例子,該REQUIRED型別方法呼叫丟擲異常,REQUIRED_NEW的方法仍然可以提交,但是NESTED還要受到REQUIRED事務回滾而被迫回滾; 這就是我認為的新的事務與內嵌事務的區別;
  2. 假設都是在一個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.