在使用Spring時大部分會用到他的聲明式事務簡單的在配置文件中進行一些規則配置利用Spring的AOP功能就能輕松搞定事務問題這裡面就涉及到一個事務的傳播屬性問題Propagation它在TransactionDefinition接口中定義以供PlatfromTransactionManager使用PlatfromTransactionManager是spring事務管理的核心接口
TransactionDefinition
public interface TransactionDefinition {
int getPropagationBehavior();
int getIsolationLevel();
int getTimeout();
boolean isReadOnly();
}
getTimeout()方法它返回事務必須在多少秒內完成
isReadOnly()事務是否只讀事務管理器能夠根據這個返回值進行優化確保事務是只讀的
getIsolationLevel()方法返回事務的隔離級別事務管理器根據它來控制另外一個事務可以看到本事務內的哪些數據
在TransactionDefinition接口中定義了五個不同的事務隔離級別ISOLATION_DEFAULT 這是一個PlatfromTransactionManager默認的隔離級別使用數據庫默認的事務隔離級別另外四個與JDBC的隔離級別相對應ISOLATION_READ_UNCOMMITTED 這是事務最低的隔離級別它充許別外一個事務可以看到這個事務未提交的數據這種隔離級別會產生髒讀不可重復讀和幻像讀
在TransactionDefinition接口中共有種選項可用
PROPAGATION_REQUIRED支持當前事務如果當前沒有事務就新建一個事務這是最常見的選擇
PROPAGATION_SUPPORTS支持當前事務如果當前沒有事務就以非事務方式執行
PROPAGATION_MANDATORY支持當前事務如果當前沒有事務就拋出異常
PROPAGATION_REQUIRES_NEW新建事務如果當前存在事務把當前事務掛起
PROPAGATION_NOT_SUPPORTED以非事務方式執行操作如果當前存在事務就把當前事務掛起
PROPAGATION_NEVER以非事務方式執行如果當前存在事務則拋出異常
PROPAGATION_NESTED支持當前事務新增Savepoint點與當前事務同步提交或回滾
現在結合一個實例應用以上各種傳播屬性來進行說明首先聲明兩個beanServiceA和ServiceB其中ServiceB被引用
ServiceA {
void methodA() {
thodB();
}
}
ServiceB {
void methodB() {
}
}
接下來我們就一一分析下
PROPAGATION_REQUIRED
加入當前正要執行的事務不在另外一個事務裡那麼就起一個新的事務比如說thodB的事務級別定義為PROPAGATION_REQUIRED 那麼由於執行thodA的時候 thodA已經起了事務這時調用thodBthodB看到自己已經運行在thodA 的事務內部就不再起新的事務而假如thodA運行的時候發現自己沒有在事務中他就會為自己分配一個事務 這樣在thodA或者在thodB內的任何地方出現異常事務都會被回滾即使thodB的事務已經被 提交但是thodA在接下來fail要回滾thodB也要回滾
PROPAGATION_SUPPORTS
如果當前在事務中即以事務的形式運行如果當前不再一個事務中那麼就以非事務的形式運行
PROPAGATION_MANDATORY
必須在一個事務中運行也就是說他只能被一個父事務調用否則他就要拋出異常
PROPAGATION_REQUIRES_NEW
比如我們設計thodA的事務級別為PROPAGATION_REQUIREDthodB的事務級別為PROPAGATION_REQUIRES_NEW 那麼當執行到thodB的時候thodA所在的事務就會掛起thodB會起一個新的事務等待thodB的事務完成以後 他才繼續執行他與PROPAGATION_REQUIRED 的事務區別在於事務的回滾程度了因為thodB是新起一個事務那麼就是存在 兩個不同的事務如果thodB已經提交那麼thodA失敗回滾thodB是不會回滾的如果thodB失敗回滾 如果他拋出的異常被thodA捕獲thodA事務仍然可能提交
PROPAGATION_NOT_SUPPORTED
當前不支持事務比如thodA的事務級別是PROPAGATION_REQUIRED 而thodB的事務級別是PROPAGATION_NOT_SUPPORTED 那麼當執行到thodB時thodA的事務掛起而他以非事務的狀態運行完再繼續thodA的事務
PROPAGATION_NEVER
不能在事務中運行假設thodA的事務級別是PROPAGATION_REQUIRED 而thodB的事務級別是PROPAGATION_NEVER 那麼thodB就要拋出異常了
PROPAGATION_NESTED
理解Nested的關鍵是savepoint他與PROPAGATION_REQUIRES_NEW的區別是PROPAGATION_REQUIRES_NEW另起一個事務將會與他的父事務相互獨立 而Nested的事務和他的父事務是相依的他的提交是要等和他的父事務一塊提交的也就是說如果父事務最後回滾他也要回滾的 而Nested事務的好處也是他有一個savepoint
ServiceA {
void methodA() {
try {
thodB();
} catch (Exception e) {
thodC();
}
}
}
也就是說thodB失敗回滾那麼thodA會回滾到savepoint點上thodA可以選擇另外一個分支比如 thodC繼續執行來嘗試完成自己的事務但是這個事務並沒有在EJB標准中定義
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28910.html