天天看點

事務的7種傳播行為

事務的7種傳播行為

事務傳播行為指的是當一個事務方法被另一個事務方法調用時,這個方法是怎麼運作的。

轉載:https://blog.csdn.net/soonfly/article/details/70305683

舉例說明:有兩個事務方法,一個是方法A,一個是方法B,方法A中調用了方法B,那方法B是開啟一個事務運作還是在方法A中的事務中運作,是由方法B的事務傳播行為控制的。

在Spring中定義了7中事務傳播行為:

傳播行為

含義

PROPAGATION_REQUIRED

表示目前方法必須運作在事務中,如果目前事務存在,方法将會在該事務中運作,否則,會啟動一個新的事務

PROPAGATION_SUPPORTS

表示該方法不需要事務上下文,但是如果存在目前的事務的話,那麼該方法會在這個事務彙總運作

PROPAGATION_MANDATORY

表示該方法必須在事務中運作,如果目前事務不存在,則會抛出一個異常

PROPAGATION_REQUIRED_NEW

表示目前方法必須運作在它自己的事務中。一個新的事務将被啟動,如果存在目前事務,在該方法執行期間,當期事務會被挂起。如果使用JTATransactionManager的話,則需要通路TransactionManager

PROPAGATION_NOT_SUPPORTED

表示目前方法不應該運作在事務中,如果存在目前事務,在該方法運作期間,目前事務将被挂起,如果使用JTATransactionManager的話,則需要通路TransactionManager

PROPAGATION_NEVER

表示目前方法不應該運作在事務上下文中,如果目前正有一個事務在運作,則抛出異常

PROPAGATION_NESTED

表示如果目前已經存在一個事務,那麼該方法将會在嵌套事務中運作。嵌套的事務可以獨立于目前事務進行單獨的送出或復原。如果目前事務不存在,那麼其行為和 PROPAGATION_REQUIRED一樣。注意各廠商對這種傳播行為的支援是有所差異的,可以參考資料總管的文檔來确認它們是夠支援嵌套事務

存在事務就支援該事務,不存在則開啟一個事務

事務的7種傳播行為

示範代碼:

單獨調用方法B,因為上下文不存在事務,是以會開啟一個事務

當調用方法A時,因為上下文不存在事務,是以會開啟一個事務,當執行到方法B時,方法B發現存在一個事務,方法B就不會開啟新的事務,而是在方法A中的事務中執行。

如果存在事務則支援目前事務,如果不存在事務則無事務運作

單獨調用方法B,無事務運作

調用方法A,方法B加入方法A的事務,事務的運作

如果存在一個事務,則事務的運作,沒有事務則抛出異常

直接調用方法B,因為沒有事務所有會抛出異常

<code>No existing transaction found for transaction marked with propagation 'mandatory'</code>

調用方法A,方法B會加入到方法A的事務中去

事務的7種傳播行為

使用PROPAGATION_REQUIRES_NEW,需要使用 JtaTransactionManager作為事務管理器。

會開啟一個事務,如果存在一個事務,則會把存在的事務挂起

當調用

相當于調用

在這裡,把ts1稱為外層事務,ts2稱為内層事務。從上面的代碼可以看出,ts2與ts1是兩個獨立的事務,互不相幹。Ts2是否成功并不依賴于 ts1。如果methodA方法在調用methodB方法後的doSomeThingB方法失敗了,而methodB方法所做的結果依然被送出。而除了 methodB之外的其它代碼導緻的結果卻被復原了

PROPAGATION_NOT_SUPPORTED總是非事務的運作,并且挂起任何存在的事務,使用PROPAGATION_NOT_SUPPORTED,也需要使用JtaTransactionManager作為事務管理器。

事務的7種傳播行為

總是非事務的運作,如果存在一個活動的事務,則抛出異常

事務的7種傳播行為

如果一個活動的事務存在,則運作在一個嵌套事務中,如果沒有活動事務,則按照PROPAGATION_REQUIRED屬性執行

這是一個嵌套事務,使用JDBC 3.0驅動時,僅僅支援DataSourceTransactionManager作為事務管理器。

需要JDBC 驅動的java.sql.Savepoint類。使用PROPAGATION_NESTED,還需要把PlatformTransactionManager的nestedTransactionAllowed屬性設為true(屬性值預設為false)。

單獨執行方法B,按照PROPAGATION_REQUIRED屬性執行

如果調用方法A,相當于如下效果:

當methodB方法調用之前,調用setSavepoint方法,儲存目前的狀态到savepoint。如果methodB方法調用失敗,則恢複到之前儲存的狀态。但是需要注意的是,這時的事務并沒有進行送出,如果後續的代碼(doSomeThingB()方法)調用失敗,則復原包括methodB方法的所有操作。嵌套事務一個非常重要的概念就是内層事務依賴于外層事務。外層事務失敗時,會復原内層事務所做的動作。而内層事務操作失敗并不會引起外層事務的復原。

它們非常類似,都像一個嵌套事務,如果不存在一個活動的事務,都會開啟一個新的事務。

使用 PROPAGATION_REQUIRES_NEW時,内層事務與外層事務就像兩個獨立的事務一樣,一旦内層事務進行了送出後,外層事務不能對其進行復原。兩個事務互不影響。兩個事務不是一個真正的嵌套事務。同時它需要JTA事務管理器的支援。

使用PROPAGATION_NESTED時,外層事務的復原可以引起内層事務的復原。而内層事務的異常并不會導緻外層事務的復原,它是一個真正的嵌套事務。DataSourceTransactionManager使用savepoint支援PROPAGATION_NESTED時,需要JDBC 3.0以上驅動及1.4以上的JDK版本支援。其它的JTATrasactionManager實作可能有不同的支援方式。

PROPAGATION_REQUIRES_NEW 啟動一個新的, 不依賴于環境的 “内部” 事務. 這個事務将被完全 commited 或 rolled back 而不依賴于外部事務, 它擁有自己的隔離範圍, 自己的鎖, 等等. 當内部事務開始執行時, 外部事務将被挂起, 内務事務結束時, 外部事務将繼續執行。

另一方面, PROPAGATION_NESTED 開始一個 “嵌套的” 事務, 它是已經存在事務的一個真正的子事務. 潛套事務開始執行時, 它将取得一個 savepoint. 如果這個嵌套事務失敗, 我們将復原到此 savepoint. 潛套事務是外部事務的一部分, 隻有外部事務結束後它才會被送出。

由此可見, PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大差別在于, PROPAGATION_REQUIRES_NEW 完全是一個新的事務, 而 PROPAGATION_NESTED 則是外部事務的子事務, 如果外部事務 commit, 嵌套事務也會被 commit, 這個規則同樣适用于 roll back.