Spring事務管理中@Transactional的propagation參數

  關於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)
    publicvoid aMethod {
        B b = newB();
        b.bMethod();
    }
}
 
//in B.java
Class B {
    @Transactional(propagation=propagation.REQUIRED)
    publicvoid 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傳播性的邏輯含義比較模糊,因此一般是不推薦使用的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章