事物回滾

有的時候方法A()裏面包含方法B(),C()

Transactional(rollbackFor = Exception.class)
public void A(){
 B();
 c();
}

@Transactional(rollbackFor = Exception.class)
public void B(){

}

@Transactional(rollbackFor = Exception.class)
public void C(){

}

 

 

這個時候當B方法內部有異常的時候,即使你在B方法內部捕獲到了,方法A中對數據庫做的操作還是會回滾的,這個是以爲方法B有異常了,把整個事物設置爲readonly了,在commit的時候就會報錯

 

那麼怎麼能讓方法B內部回滾,方法A不回滾的,現實中也是有這樣的業務存在的,比如:工作流審批,我審批通過了,要下傳下游接口,這個時候接口報錯了,不能以爲接口報錯整個工作流都要回滾,這個明顯是不符合業務邏輯的。 那麼有沒有方法解決呢。

這個就要區分了:

1.在方法B()上加下面的註解

@Transactional(rollbackFor = Exception.class,propagation =Propagation.REQUIRES_NEW)

從字面即可知道,new,每次都要一個新事務,該傳播級別的特點是,每次都會新建一個事務,並且同時將上下文中的事務掛起,執行當前新建事務完成以後,上下文事務恢復再執行。

也就是說我在執行B方法的時候是新開了一個事物,即使方法B中有異常回滾,A方法也不會回滾。這個比較適合比較獨立的業務邏輯。但是如果我在方法A中執行了一個插入操作,由於事物還沒有提交,當我進入方法B時,是新開了一個事物,這個我們想查到A中插入的數據是查不到的。

2.在方法B()上加下面的註解

@Transactional(rollbackFor = Exception.class,propagation = Propagation.NESTED)


Propagation.NESTED解釋:

字面也可知道,nested,嵌套級別事務。該傳播級別特徵是,如果上下文中存在事務,則嵌套事務執行,如果不存在事務,則新建事務。

那麼什麼是嵌套事務呢?很多人都不理解,我看過一些博客,都是有些理解偏差。

嵌套是子事務套在父事務中執行,子事務是父事務的一部分,在進入子事務之前,父事務建立一個回滾點,叫save point,然後執行子事務,這個子事務的執行也算是父事務的一部分,然後子事務執行結束,父事務繼續執行。重點就在於那個save point。看幾個問題就明瞭了:

如果子事務回滾,會發生什麼?

父事務會回滾到進入子事務前建立的save point,然後嘗試其他的事務或者其他的業務邏輯,父事務之前的操作不會受到影響,更不會自動回滾。

如果父事務回滾,會發生什麼?

父事務回滾,子事務也會跟着回滾!爲什麼呢,因爲父事務結束之前,子事務是不會提交的,我們說子事務是父事務的一部分,正是這個道理。那麼:

事務的提交,是什麼情況?

是父事務先提交,然後子事務提交,還是子事務先提交,父事務再提交?答案是第二種情況,還是那句話,子事務是父事務的一部分,由父事務統一提交。

也就是說:

我在方法B中的事物就相當於是方法A的的一個子事物,A是B是父級事物,當方法B異常回滾到方法A沒有執行B之前,然後執行下面的方法C,這個是傳播方式的好處是,子事物可以共享父事物裏面的東西,比如我在父事物中執行一個插入操作,那麼在子事物可以查到這個插入的數據。

參考地址:https://www.cnblogs.com/wj0816/p/8474743.html

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