程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> Spring事務傳遞性探討,spring事務傳遞

Spring事務傳遞性探討,spring事務傳遞

編輯:JAVA綜合教程

Spring事務傳遞性探討,spring事務傳遞


本篇主要討論下面幾點獲取【下載地址】  :

一: Spring 事務的傳遞性介紹

二: 第三方調用含有事務的Service拋異常方法探討

 

一: Spring 事務的傳遞性介紹

    事務傳播行為,所謂事務的傳播行為是指,如果在開始當前事務之前,一個事務上下文已經存在,此時有若干選項可以指定一個事務性方法的執行行為。在TransactionDefinition定義中包括了如下幾個表示傳播行為的常量:

    TransactionDefinition.PROPAGATION_REQUIRED:如果當前存在事務,則加入該事務;如果當前沒有事務,則創建一個新的事務。

    TransactionDefinition.PROPAGATION_REQUIRES_NEW:創建一個新的事務,如果當前存在事務,則把當前事務掛起。

    TransactionDefinition.PROPAGATION_SUPPORTS:如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續運行。

    TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事務方式運行,如果當前存在事務,則把當前事務掛起。

    TransactionDefinition.PROPAGATION_NEVER:以非事務方式運行,如果當前存在事務,則拋出異常。

    TransactionDefinition.PROPAGATION_MANDATORY:如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。

    TransactionDefinition.PROPAGATION_NESTED:如果當前存在事務,則創建一個事務作為當前事務的嵌套事務來運行;如果當前沒有事務,則該取值等價TransactionDefinition.PROPAGATION_REQUIRED。

    這裡需要指出的是,前面的六種事務傳播行為是 Spring 從 EJB 中引入的,他們共享相同的概念。而 PROPAGATION_NESTED是 Spring 所特有的。以 PROPAGATION_NESTED 啟動的事務內嵌於外部事務中(如果存在外部事務的話),此時,內嵌事務並不是一個獨立的事務,它依賴於外部事務的存在,只有通過外部的事務提交,才能引起內部事務的提交,嵌套的子事務不能單獨提交。如果熟悉 JDBC 中的保存點(SavePoint)的概念,那嵌套事務就很容易理解了,其實嵌套的子事務就是保存點的一個應用,一個事務中可以包括多個保存點,每一個嵌套子事務。另外,外部事務的回滾也會導致嵌套子事務的回滾。

 

二: 第三方調用含有事務的Service拋異常方法探討

    假設術語如下:調用方Conumer,  調用Service的methodA, methodA調用Service的 methodB

    a)methodA 傳播屬性為required, methodB傳播屬性為required, 代碼如下

     

Java代碼  收藏代碼
  1. public void methodA() {  
  2.     try {  
  3.        methodB();  
  4.     } catch(Exception e) {  
  5.        process();  
  6.     }  
  7.     otherOperation;  
  8. }  
      假設MethodB拋出異常,則Consumer調用MethodA會發生怎樣的情形? 

    發現Consumer調用MethodA的時候出現了運行時異常,UnexpectedRollbackException: “Transaction rolled back because it has been marked as rollback-only”。這是為什麼呢?

    網上搜索了下,終於發現了一個合理的解釋。當MethodA調用MethodB的時候,且兩個方法都為required屬性,則methodA和methodB共享一個事務,當methodB拋出了異常,則共享事務回滾,但是被MethodA catch了,而MethodA又沒有及時拋出異常,則MethodA正常執行到最後的時候,則會做提交事務的操作,但是事務已經被回滾了,所以才出現了上面的異常。

 

    既然這樣,小弟就開始YY了一下,哪些情況會使調用方沒有這個異常呢?經過與小伙伴們的思維碰撞,發現有一下幾個方法。

   b) MethodA 不加事務,所以執行到最後就不會commit,SUPPORTS和NOT_SUPPORTED都可以實現這種功能。

   c) MethodB 設置不共享事務,擁有自己單獨的事務。驗證發現,REQUIRES_NEW可以實現這種功能。

   

   然後又YY了下,既然一個回滾的事務不能提交了,那麼這個回滾的事務可以重復回滾嗎?

   d) MethodA 調用MethodB,如果MethodA不catch MethodB,則調用方會怎麼樣?很簡單當然直接捕獲到MethodB的異常了,但是感覺這個場景不能完全反應初回滾的事務是否可以重復回滾。代碼如下:

Java代碼  收藏代碼
  1. public void methodA() {  
  2.     methodB();  
  3.     otherOperation;  
  4. }  

 

  e) 還有什麼場景可以模擬回滾的事務是否可以再回滾呢?看,代碼如下:

     

Java代碼  收藏代碼
  1. public void methodA() {  
  2.     try {  
  3.        methodB();  
  4.     } catch(Exception e) {  
  5.        process();  
  6.     }  
  7.     try {  
  8.        methodB();  
  9.     } catch(Exception e) {  
  10.        process();  
  11.     }  
  12.     System.out.println("**************");  
  13.     otherOperation;  
  14. }  

   第一個MethodB已經回滾了共享的事務,第二個MethodB同樣會拋出異常回滾共享的事務,如果執行了後面的System.out,則說明事務可以多次回滾。測試發現打印出來了後面的SysOut的內容,所以猜測可能是這樣回滾事務的時候如果發現事務已經回滾,則直接跳過。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved