關於Spring事務管理中@Transactional的其他配置問題,請參看http://deltamaster.is-programmer.com/posts/28488.html。
本文重點講一講propagation參數,propagation配置的就是一個事務的傳播性問題。
所謂事務傳播性,就是被調用者的事務與調用者的事務之間的關係。舉例說明。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
//in
A.java Class
A { @Transactional (propagation=propagation.REQUIRED) public void
aMethod { B
b = new B(); b.bMethod(); } } //in
B.java Class
B { @Transactional (propagation=propagation.REQUIRED) public void
bMethod { //something
} } |
在上面這個例子中,傳播性被設爲了REQUIRED,注意,這是默認值,也即不進行該參數配置等於配置成REQUIRED。
REQUIRED的含義是,支持當前已經存在的事務,如果還沒有事務,就創建一個新事務。在上面這個例子中,假設調用aMethod前不存在任何事務,那麼執行aMethod時會自動開啓一個事務,而由aMethod調用bMethod時,由於事務已經存在,因此會使用已經存在的事務(也就是執行aMethod之前創建的那個事務)。
對於這樣的配置,如果bMethod過程中發生異常需要回滾,那麼aMethod中所進行的所有數據庫操作也將同時被回滾,因爲這兩個方法使用了同一個事務。
MANDATORY的含義是,支持當前已經存在的事務,如果還沒有事務,就拋出一個異常。如果上例中aMethod的傳播性配置爲MANDATORY,我們就無法在沒有事務的情況下調用aMethod,因此,傳播性爲MANDATORY的方法必定是一個其他事務的子事務,當邏輯上獨立存在沒有意義或者可能違反數據、事務完整性的時候,就可以考慮設置這樣的傳播性設置。
NESTED的含義是,在當前事務中創建一個嵌套事務,如果還沒有事務,那麼就簡單地創建一個新事務。
REQUIRES_NEW的含義是,掛起當前事務,創建一個新事務,如果還沒有事務,就簡單地創建一個新事務。
請注意以上兩者的區別,大多數情況下一上兩種傳播性行爲是類似的,不過在事務回滾的問題上,以上兩者有很大的區別。
首先,REQUIRES_NEW會創建一個與原事務無關的新事務,儘管是由一個事務調用了另一個事務,但卻沒有父子關係。
如果bMethod的傳播性是REQUIRES_NEW,而拋出了一個異常,則bMethod一定會被回滾,而如果aMethod捕獲並處理了這個bMethod拋出的異常,那麼aMethod仍有可能成功提交。當然,如果aMethod沒有處理這個異常,那麼aMethod也會被回滾。
如果aMethod在bMethod完成後出現了異常,那麼bMethod已經提交而無法回滾,只有aMethod被回滾了。
而對於NESTED,雖然也會創建一個新事務,但是這個事務與調用者是有父子關係的相互依存的。
如果bMethod的傳播性是NESTED,而拋出了一個異常,事務的回滾行爲與REQUIRES_NEW是一致的。
但是如果aMethod在bMethod完成後出現了異常,bMethod同樣也會被回滾。因爲事實上,EJB中沒有對於NESTED傳播性的類似實現,NESTED並不是真正啓動了一個事務,而是開啓了一個新的savepoint。
NEVER的含義很簡單,就是強制要求不在事務中運行,如果當前存在一個事務,則拋出異常,因此如果bMethod傳播性是NEVER,則一定拋出異常。
NOT_SUPPORTED的含義是,強制不在事務中運行,如果當前存在一個事務,則掛起該事務。
SUPPORTS的含義是,支持當前事務,如果沒有事務那麼就不在事務中運行。SUPPORTS傳播性的邏輯含義比較模糊,因此一般是不推薦使用的。