例如:事務中 有A,B,C,D等幾個方法。 B 中的方法是往數據庫中插入數據。
現在問題是 在 D方法中 產生了異常,導致B插入的數據也沒了,
有沒有方法,在D 異常的時候 A和C能回滾 但是B不回滾
Spring有以下幾種事務傳播行爲可配置:
PROPAGATION_REQUIRED
支持當前事務,如果當前沒有事務,就新建一個事務。
PROPAGATION_SUPPORTS
支持當前事務,如果當前沒有事務,就以非事務方式執行。
PROPAGATION_MANDATORY
支持當前事務,如果當前沒有事務,就拋出異常。
PROPAGATION_REQUIRES_NEW
新建事務,如果當前存在事務,把當前事務掛起,新建一個事務。
PROPAGATION_NOT_SUPPORTED
以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
PROPAGATION_NEVER
以非事務方式執行,如果當前存在事務,則拋出異常。
我的配置如下:
@transactional(propagation=propagation.required)
public void service(){
A();
B();
C();
D();
}
@transactional(propagation=propagation.required)
void A(){
}
@transactional(propagation=propagation.requires_new)
void B(){
}
@transactional(propagation=propagation.required)
void C(){
}
@transactional(propagation=propagation.required)
void D(){
}
雖然事務的傳播特性說道 PROPAGATION_REQUIRES_NEW 會新建一個事務,使嵌套的內部事務與外部事務保證無關性。
如果真如上面所說的話,上面的代碼,是可以運行的,不管A、B、C、D誰有異常,都會使外層service進行回滾,但是B爲新建事務,所以B不會隨着外層事務回滾而回滾。
但是實際運行,B也隨之進行回滾了,這就說明,PROPAGATION_REQUIRES_NEW 並沒有新建一個事務,爲什麼呢?
我也沒咋明白,不過找了些資料解釋說,如果要使用PROPAGATION_REQUIRES_NEW必需保證,外部事務,與嵌套事務中的新建事務,必需位於兩個service中。
詳細請參考:http://blog.csdn.net/wangjunjun2008/article/details/53669951
所以我又 新建了一個,service 接口,命名爲 NewService接口 ,實現類裏面寫入了 事務需要使用PROPAGATION_REQUIRES_NEW的B方法,並設置B方法事務爲PROPAGATION_REQUIRES_NEW,將NewService注入到,service中。代碼如下;
@autowrite
private NewService newService;
@transactional(propagation=propagation.required)
public void service(){
A();
newService.B();
C();
D();
}
@transactional(propagation=propagation.required)
void A(){
}
@transactional(propagation=propagation.required)
void C(){
}
@transactional(propagation=propagation.required)
void D(){
}
這樣當C、D方法出現異常時,B方法不會進行回滾,但是還會出現一個問題,就是當 A() 方法 出現異常,B方法依然會回滾。
這就說明,只要有異常拋出,就不會執行後面的方法,直接返回外部事務,進行回滾,所以B方法,還沒來得及新建事務,整個事務就進行回滾了。
解決辦法: 值需要將B方法提前就好了。