一般來說function2和function1用的是同一個Transaction。
這個取決於@Transactional 的 propagation設置(事務的傳播性)
默認的是
1
|
@Transactional
(propagation=propagation.REQUIRED)
|
也就是使用同一個Transaction。也可以按需求設置成 NESTED 或者 REQUIRES_NEW。
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的含義是,支持當前已經存在的事務,如果還沒有事務,就創建一個新事務。在上面這個例子中,假設調用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傳播性的邏輯含義比較模糊,因此一般是不推薦使用的。