天天看點

Spring事務的傳播行為

 本文主要介紹下Spring事務中的傳播行為。

事務傳播行為介紹

Spring中的7個事務傳播行為:

事務行為 說明

Spring事務的傳播行為

舉例說明

案例代碼

ServiceA

ServiceA {   
     void methodA() {
         ServiceB.methodB();
     }
}      

ServiceB

ServiceB { 
     void methodB() {
     }      
}      

1.PROPAGATION_REQUIRED

 假如目前正要運作的事務不在另外一個事務裡,那麼就起一個新的事務 比方說,ServiceB.methodB的事務級别定義PROPAGATION_REQUIRED, 那麼因為執行ServiceA.methodA的時候,ServiceA.methodA已經起了事務。這時調用ServiceB.methodB,ServiceB.methodB看到自己已經執行在ServiceA.methodA的事務内部。就不再起新的事務。而假如ServiceA.methodA執行的時候發現自己沒有在事務中,他就會為自己配置設定一個事務。這樣,在ServiceA.methodA或者在ServiceB.methodB内的不論什麼地方出現異常。事務都會被復原。即使ServiceB.methodB的事務已經被送出,可是ServiceA.methodA在接下來fail要復原,ServiceB.methodB也要復原

Spring事務的傳播行為

2.PROPAGATION_SUPPORTS

 假設目前在事務中。即以事務的形式執行。假設目前不在一個事務中,那麼就以非事務的形式執行

3PROPAGATION_MANDATORY

 必須在一個事務中執行。也就是說,他僅僅能被一個父事務調用。否則,他就要抛出異常

4.PROPAGATION_REQUIRES_NEW

 這個就比較繞口了。 比方我們設計ServiceA.methodA的事務級别為PROPAGATION_REQUIRED,ServiceB.methodB的事務級别為PROPAGATION_REQUIRES_NEW。那麼當運作到ServiceB.methodB的時候,ServiceA.methodA所在的事務就會挂起。ServiceB.methodB會起一個新的事務。等待ServiceB.methodB的事務完畢以後,他才繼續運作。

他與PROPAGATION_REQUIRED 的事務差别在于事務的復原程度了。由于ServiceB.methodB是新起一個事務,那麼就是存在兩個不同的事務。假設ServiceB.methodB已經送出,那麼ServiceA.methodA失敗復原。ServiceB.methodB是不會復原的。假設ServiceB.methodB失敗復原,假設他抛出的異常被ServiceA.methodA捕獲,ServiceA.methodA事務仍然可能送出。

Spring事務的傳播行為

5.PROPAGATION_NOT_SUPPORTED

 目前不支援事務。比方ServiceA.methodA的事務級别是PROPAGATION_REQUIRED 。而ServiceB.methodB的事務級别是PROPAGATION_NOT_SUPPORTED ,那麼當執行到ServiceB.methodB時。ServiceA.methodA的事務挂起。而他以非事務的狀态執行完,再繼續ServiceA.methodA的事務。

6.PROPAGATION_NEVER

 不能在事務中執行。

如果ServiceA.methodA的事務級别是PROPAGATION_REQUIRED。 而ServiceB.methodB的事務級别是PROPAGATION_NEVER ,那麼ServiceB.methodB就要抛出異常了。

7.PROPAGATION_NESTED

 如果目前存在事務,則在嵌套事務内執行。如果目前沒有事務,則執行與PROPAGATION_REQUIRED類似的操作。

Spring中事務的配置

配置檔案的方式

<tx:advice id="txAdvice" transaction-manager="txManager"> 
      <tx:attributes>  
      <!--設定所有比對的方法,然後設定傳播級别和事務隔離-->
           <tx:method name="save*" propagation="REQUIRED" /> 
           <tx:method name="add*" propagation="REQUIRED" /> 
           <tx:method name="create*" propagation="REQUIRED" /> 
           <tx:method name="insert*" propagation="REQUIRED" /> 
           <tx:method name="update*" propagation="REQUIRED" /> 
           <tx:method name="merge*" propagation="REQUIRED" /> 
           <tx:method name="del*" propagation="REQUIRED" /> 
           <tx:method name="remove*" propagation="REQUIRED" /> 
           <tx:method name="put*" propagation="REQUIRED" /> 
           <tx:method name="get*" propagation="SUPPORTS" read-only="true" /> 
           <tx:method name="count*" propagation="SUPPORTS" read-only="true" /> 
          <tx:method name="find*" propagation="SUPPORTS" read-only="true" /> 
          <tx:method name="list*" propagation="SUPPORTS" read-only="true" /> 
          <tx:method name="*" propagation="SUPPORTS" read-only="true" /> 
     </tx:attributes> 
</tx:advice>       

注解的方式

<!--開啟注解的方式--> 
<tx:annotation-driven transaction-manager="transactioManager" />      

@Transactional(propagation=Propagation.REQUIRED)

如果有事務, 那麼加入事務, 沒有的話建立一個(預設情況下)

@Transactional(propagation=Propagation.NOT_SUPPORTED)

容器不為這個方法開啟事務

@Transactional(propagation=Propagation.REQUIRES_NEW)

不管是否存在事務,都建立一個新的事務,原來的挂起,新的執行完畢,繼續執行老的事務

@Transactional(propagation=Propagation.MANDATORY)

必須在一個已有的事務中執行,否則抛出異常

@Transactional(propagation=Propagation.NEVER)

必須在一個沒有的事務中執行,否則抛出異常(與Propagation.MANDATORY相反)

@Transactional(propagation=Propagation.SUPPORTS)

如果其他bean調用這個方法,在其他bean中聲明事務,那就用事務.如果其他bean沒有聲明事務,那就不用事務.