提示
事務(wù)傳播行為率先出現(xiàn)在 Spring 框架中,HasorDB 對其思想并未有什么改進而是在 HasorDB 中提供了一套完整的實現(xiàn)。
簡單的理解就是多個事務(wù)方法相互調(diào)用時,事務(wù)如何在這些方法間傳播。舉個例子:
?方法A
? 是一個事務(wù)的方法,在執(zhí)行過程中調(diào)用了 ?方法B
?。 接下來 ?方法B
? 有無事務(wù)以及 ?方法B
? 對事務(wù)的要求不同都會對 ?方法A
?的事務(wù)具體執(zhí)行造成影響。 同時 ?方法A
? 的事務(wù)對? 方法B
? 的事務(wù)執(zhí)行也有影響,這種影響具體是什么就由兩個方法所定義的事務(wù)傳播行為所決定。
Propagation.REQUIRED
?嘗試加入已經(jīng)存在的事務(wù)中,如果沒有則開啟一個新的事務(wù)。
時間 | 事務(wù)1 | 事務(wù)2(REQUIRED) | 效果 |
---|---|---|---|
T1 | begin | ||
T2 | insert data1 | ||
T3 | begin | 什么都不做 | |
T4 | insert data2 | ||
T5 | commit/rollback | 什么都不做 | |
T5 | insert data3 | ||
T5 | commit/rollback |
Propagation.REQUIRES_NEW
?將掛起當前存在的事務(wù)掛起(如果存在的話)并且開啟一個全新的事務(wù),新事務(wù)與已存在的事務(wù)之間彼此沒有關(guān)系。
DataSourceManager
? 中正在使用的同步資源被臨時保存
DataSourceManager
?會得到一個全新的數(shù)據(jù)庫連接。
時間 | 事務(wù)1 | 事務(wù)2(REQUIRES_NEW) | 效果 |
---|---|---|---|
T1 | begin | ||
T2 | insert data1 | ||
T3 | begin | 產(chǎn)生新的連接并且和當前線程綁定,以滿足 本地同步 | |
T4 | insert data2 | 在新連接上寫入 | |
T5 | commit/rollback | 操作新的 Connection
|
|
T5 | insert data3 | ||
T5 | commit/rollback |
Propagation.NESTED
?在當前事務(wù)中通過 ?Savepoint
? 方式開啟一個子事務(wù)。
時間 | 事務(wù)1 | 事務(wù)2(NESTED) | 效果 |
---|---|---|---|
T1 | begin | ||
T2 | insert data1 | ||
T3 | begin | 創(chuàng)建事務(wù)保存點 | |
T4 | insert data2 | ||
T5 | commit/rollback | commit 會釋放保存點、rollback 會回退到 T3 | |
T5 | insert data3 | ||
T5 | commit/rollback |
Propagation.SUPPORTS
?如果當前沒有事務(wù)存在,就以非事務(wù)方式執(zhí)行;如果有,就使用當前事務(wù)。以下面的執(zhí)行為例:
SUPPORTS
?行為是事務(wù)傳播屬性中最簡單的一種行為,其行為本質(zhì)上強調(diào)了 不作為
時間 | 事務(wù)1 | 事務(wù)2(SUPPORTS) | 效果 |
---|---|---|---|
T1 | begin | ||
T2 | insert data1 | ||
T3 | begin | ||
T4 | insert data2 | 注1 若 T1 開啟了事務(wù),那么效果等同于 REQUIRED
|
|
T5 | commit/rollback | 什么都不做 | |
T5 | insert data3 | ||
T5 | commit/rollback |
Connection
?對象的 ?autoCommit
?屬性為 ?false
?。
能夠?qū)е聠邮聞?wù)的傳播行為有 ?REQUIRED
?、?REQUIRES_NEW
?和 ?NESTED
?,如果使用 低級別 API 手動改變 autoCommit 狀態(tài)也會導(dǎo)致進入事務(wù)狀態(tài)。Propagation.NOT_SUPPORTED
?如果當前沒有事務(wù)存在,就以非事務(wù)方式執(zhí)行;如果有,就將當前事務(wù)掛起。以下面的執(zhí)行為例:
注意
將掛起當前存在的事務(wù)掛起(如果存在的話)并且開啟一個全新的事務(wù),新事務(wù)與已存在的事務(wù)之間彼此沒有關(guān)系。
- 掛起會導(dǎo)致 ?
DataSourceManager
?中正在使用的同步資源被臨時保存。
- 在掛起之后訪問 ?
DataSourceManager
?會得到一個全新的數(shù)據(jù)庫連接。
時間 | 事務(wù)1 | 事務(wù)2(NOT_SUPPORTED) | 效果 |
---|---|---|---|
T1 | begin | ||
T2 | insert data1 | ||
T3 | begin | 注1 若 T1 開啟了事務(wù),那么會掛起當前事務(wù)。但不開啟新的事務(wù) | |
T4 | insert data2 | ||
T5 | commit/rollback | 注2 若 T3 掛起了事務(wù),那么會恢復(fù)它。 | |
T5 | insert data3 | ||
T5 | commit/rollback |
Connection
?對象的 ?autoCommit
?屬性為 ?false
?。 能夠?qū)е聠邮聞?wù)的傳播行為有 ?REQUIRED
?、?REQUIRES_NEW
?和 ?NESTED
?,如果使用 低級別 API 手動改變 ?autoCommit
?狀態(tài)也會導(dǎo)致進入事務(wù)狀態(tài)。DataSourceManager
?的當前綁定連接為之前的那一個。Propagation.NEVER
?如果當前沒有事務(wù)存在,就以非事務(wù)方式執(zhí)行;如果有就拋出異常。
時間 | 事務(wù)1 | 事務(wù)2(NEVER) | 效果 |
---|---|---|---|
T1 | begin | ||
T2 | insert data1 | ||
T3 | begin | 注1 若 T1 開啟了事務(wù),那么會拋出異常 | |
T4 | insert data2 | ||
T5 | commit/rollback | 什么都不做 | |
T5 | insert data3 | ||
T5 | commit/rollback |
NOT_SUPPORTED
? 那么 T3 環(huán)節(jié)上 ?NEVER
?行為就不會報錯。它的行為會和 ?SUPPORTS
?等價。 若 T1 這個動作導(dǎo)致了 ?Connection
?對象的 ?autoCommit
?屬性為 ?false
?那么 T3 環(huán)節(jié)就會報錯。autoCommit
?為 ?false
?傳播行為有 ?REQUIRED
?、?REQUIRES_NEW
?和 ?NESTED
?,也可以通過使用 低級別 API 改變。Propagation.MANDATORY
?如果當前沒有事務(wù)存在,就拋出異常;如果有,就使用當前事務(wù)。
時間 | 事務(wù)1 | 事務(wù)2(NEVER) | 效果 |
---|---|---|---|
T1 | begin | ||
T2 | insert data1 | ||
T3 | begin | 注1 若 T1 不存在事務(wù),那么會拋出異常 | |
T4 | insert data2 | ||
T5 | commit/rollback | 什么都不做 | |
T5 | insert data3 | ||
T5 | commit/rollback |
MANDATORY
?是要求必須 T1 環(huán)節(jié)產(chǎn)生了一個事務(wù),否則會報錯。 因此若 T1 環(huán)節(jié)使用的是? NOT_SUPPORTED
?行為,那么 T3 環(huán)節(jié)就會報錯。
更多建議: