本文主要介紹下Spring事務中的傳播行為。
事務傳播行為介紹
Spring中的7個事務傳播行為:
事務行為 說明
舉例說明
案例代碼
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也要復原
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事務仍然可能送出。
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沒有聲明事務,那就不用事務.