首先咱們知道,spring的事務管理有如下幾種事務屬性:
PROPAGATION_REQUIRED--支持當前事務,若是當前沒有事務,就新建一個事務。這是最多見的選擇。
PROPAGATION_SUPPORTS--支持當前事務,若是當前沒有事務,就以非事務方式執行。
PROPAGATION_MANDATORY--支持當前事務,若是當前沒有事務,就拋出異常。
PROPAGATION_REQUIRES_NEW--新建事務,若是當前存在事務,把當前事務掛起。
PROPAGATION_NOT_SUPPORTED--以非事務方式執行操做,若是當前存在事務,就把當前事務掛起。
PROPAGATION_NEVER--以非事務方式執行,若是當前存在事務,則拋出異常。
PROPAGATION_NESTED--若是當前存在事務,則在嵌套事務內執行。若是當前沒有事務,則進行與PROPAGATION_REQUIRED 相似的操做。
=======================
針對這些事務屬性,我作了幾回試驗。
使用的代碼簡單描述就是:
外層方法{
try{內層方法();}catch(RuntimeException e){}
}
內層方法(){
拋出 RuntimeException ;
}
=======================
對REQUIRED的試驗時,配置是:
<tx:method name="外層方法" propagation="REQUIRED" />
<tx:method name="內層方法" propagation="REQUIRED" />
在日誌中看到:
1、爲外層方法建立事務
- Creating new transaction with name [外層方 法]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2、爲內層方法配置事務
- Participating in existing transaction
能夠看到
,內層方法使用的是外層方法的事務上下文。而後,當內層方法拋出異常時,日誌中記錄:
Setting JDBC transaction [...] rollback-only
即要求該事務回滾。可是內層方法的異常被外層方法捕獲並處理了, 外層方法仍然會繼續執行,並在執行完畢後提交事務。這時日誌中記錄並拋出異常:
Global transaction is marked as rollback-only but transactional code requested commit
(執行事務回滾...)
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
所謂
「支持當前事務」
,
就是在當前事務的上下文內執行目標方法。
內層方法對事務的操做會影響到外層方法。
=========================
對
NESTED
的試驗時,配置以下:
<tx:method name="外層方法" propagation="REQUIRED" />
<tx:method name="內層方法" propagation="NESTED" />
在日誌中看到:
1、爲外層方法建立事務
- Creating new transaction with name [外層方 法]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2、爲內層方法建立嵌套事務
-
Creating nested transaction with name [
內層方法
]
一、
內層方法回滾、提交
- Rolling back transaction to savepoint
二、
外層方法繼續執行並提交
外層方法邏輯輸出
- Triggering beforeCommit synchronization
……
可見,嵌套事務與當前事務能夠認爲是兩個事務,只是它不會掛起當前事務。嵌套事務即便回滾,當前事務仍然能夠正常提交。
=======================
對SUPPORTS試驗時, 使用的配置是:
<tx:method name="外層方法" propagation="SUPPORTS" />
<tx:method name="內層方法" propagation="
REQUIRED
" />
另外內層方法改成了:
內層方法(){
return;
}
這種方案下,日誌中只有爲內層方法建立事務的記錄,對外層方法基本是「漠不關心」的。而若是把配置反過來,改爲
<tx:method name="外層方法" propagation="
REQUIRED
" />
<tx:method name="內層方法" propagation="SUPPORTS" />
那麼,
spring會爲外層方法建立事務,而對內存方法則使用外層方法的事務上下文。
可是,若是配置爲:
<tx:method name="外層方法" propagation="SUPPORTS" />
<tx:method name="內層方法" propagation="SUPPORTS" />
日誌中會出現幾行這樣的記錄:
Triggering beforeCommit synchronization
Triggering beforeCompletion synchronization
Triggering afterCommit synchronization
Triggering afterCompletion synchronization
這些是事務提交先後的日誌;可是卻找不到建立事務相關的日誌。我不清楚爲何會出現這種事務先後行爲不匹配的狀況。之後再琢磨琢磨吧。
======================
其它的幾種狀況我沒有再測試了。不過,事務相關配置的基本含義到這裏差很少已經清楚了,其它的狀況能夠「同理可證」或者「由此推知」了吧。