spring事務聲明的幾種傳播特性

近來遇到了一個spring業務致使的疑問,所以寫了幾個小程序瞭解了一下業務的傳達特性,下面別離舉比如別離看看業務的傳達特性。

業務的幾種傳達特性
1. PROPAGATION_REQUIRED: 假如存在一個業務,則支撐當時業務。假如沒有業務則敞開
Java代碼 保藏代碼
/** 
* TransactionTestService test1和test2配有業務(PROPAGATION_REQUIRED) */ 
public interface TransactionTestService { 
//業務特點 PROPAGATION_REQUIRED 
public void test1() throws Exception{

澳洲保健品http://www.eget.com.au
國醫一號http://www.tdhzp.com
號碼大全http://www.haomad.com
臨沂購http://www.shoudashou.com 
avInfoTaskTunnel.insertAvInfoTask(); 
test2(); 

//業務特點 PROPAGATION_REQUIRED 
public void test2() throws Exception{ 
avRequestTunnel.insertAvRequest(); 
throw new Exception(); 



/** 
* main 
*/ 
public class TransactionTestMain { 

public static void main(String[] args) throws Exception{ 
TransactionTestService transactionTestService = (TransactionTestService)context.getBean("transactionTestService"); 
try { 
transactionTestService.test1(); 
} catch (Exception e) { 



上述代碼中test1()和test2()都配有PROPAGATION_REQUIRED業務特點,test1()內部調用test2(),這樣test1()和test2()辦法將都處於同一業務傍邊,當在test2()中拋出反常,會致使test1()和test2()辦法中的業務都回滾。
可是,假如test1()辦法對調用test2()時捕獲反常,成果會是如何的呢? test1應該能正常寫入沒疑問,那麼test2呢?
Java代碼 保藏代碼
//test1()中捕獲test2()拋出的反常 
public void test1() throws Exception{ 
avInfoTaskTunnel.insertAvInfoTask(); 
try { 
test2(); 
}catch (Exception e) { 



最後的成果test2()也將會正常的寫入。本來,上面狀況中假如僅僅test1()配有PROPAGATION_REQUIRED業務特點,test2()不裝備任何業務特點,發作的成果也是共同的。上面的景象相當於:
Java代碼 保藏代碼
public static void main(String[] args) throws Exception{ 
Connection con = null; 
try { 
con=getConnection(); 
con.setAutoCommit(false); 
transactionTestService.test1(); //test1()和test2()處於同一業務傍邊 
con.commit(); 
} catch (Exception e) { 
con.rollback(); 
} finally { 
closeCon(); 


上述test1()和test2()是同一個類的兩個辦法,那麼要是它們處於不相同類呢?
Java代碼 保藏代碼
//main函數不變,test1()中調用test2()地方換成調用另一個類中配有PROPAGATION_REQUIRED業務特點的辦法 
//不對otherService.test2()捕獲反常的景象就沒必要說了,一定都回滾。 
public void test1() throws Exception{ 
avInfoTaskTunnel.insertAvInfoTask(); 
try { 
otherService.test2(); //PROPAGATION_REQUIRED業務特點 
} catch (Exception e) { 



//otherService.test2() 
public void test2() throws Exception{ 
avRequestTunnel.insertAvRequest(); 
throw new Exception(); 

上述相同捕獲了反常,可是成果會如何呢? 成果有點出人意料,與之前test1(),test2()處於同一類的景象不相同,這個時分,兩個辦法都將回滾,而且在調用test1()的地方會拋出下面反常。這是因爲子業務在回滾的時分現已將主業務符號成了rollback-only,這樣致使主業務在提交的時分就會拋出下面這個反常。 別的:假如otherService.test2()沒有裝備任何業務特點,那麼test2()拋出反常的時分,將致使test1()和test2()都回滾。
Java代碼 保藏代碼
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only 
上述狀況網上查詢到一種處理辦法是在transactionManager中將globalRollbackOnParticipationFailure 設置爲false(默認是true)。可是這樣又帶來另一個疑問,子業務也給一併提交了(這個時分子業務發生反常,不想提交),詳細的處理辦法還沒找到,可是我覺得不應該將這兩個裝備在同一業務中。
Xml代碼 保藏代碼
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 






2. PROPAGATION_SUPPORTS: 假如存在一個業務,支撐當時業務。假如沒有業務,則非業務的履行
Java代碼 保藏代碼
//TransactionTestService test1()配有業務(PROPAGATION_SUPPORTS) 
public void test1() throws Exception{ 
avInfoTaskTunnel.insertAvInfoTask(); 
throw new Exception(); 



/** 
* main 
*/ 
public class TransactionTestMain { 

public static void main(String[] args) throws Exception{ 
TransactionTestService transactionTestService = (TransactionTestService)context.getBean("transactionTestService"); 
try { 
transactionTestService.test1(); 
} catch (Exception e) { 



TransactionTestService的test1()配有PROPAGATION_SUPPORTS業務特點,咱們曉得這種景象下假如配的是PROPAGATION_REQUIRED業務特點,那麼test1()將新建業務運轉,可是PROPAGATION_SUPPORTS特點不會新建,這種景象下,test1()辦法將正常提交。那假如是外層業務配有業務呢?如下所示,此種景象test2()將處於業務傍邊了。
Java代碼 保藏代碼
//PROPAGATION_REQUIRED業務特點 
public void test1() throws Exception{ 
avInfoTaskTunnel.insertAvInfoTask(); 
test2(); 

//PROPAGATION_SUPPORTS業務特點 
public void test2() throws Exception{ 
avRequestTunnel.insertAvRequest(); 
throw new Exception(); 


3. PROPAGATION_MANDATORY: 假如現已存在一個業務,支撐當時業務。假如沒有一個活動的業務,則拋出反常。

Java代碼 保藏代碼
//景象1:PROPAGATION_REQUIRED業務特點 景象2:不配任何業務特點 
public void test1() throws Exception{ 
avInfoTaskTunnel.insertAvInfoTask(); 
otherService.test2(); 

//otherService的test2()裝備PROPAGATION_MANDATORY業務特點 
public void test2() throws Exception { 
avRequestTunnel.insertAvRequest(); 
throw new Exception(); 


//test1()處於景象2時拋出反常,test2()不能夠提交,可是test1()卻是能夠成功提交的 
org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory' 
上述狀況,當test1()處於景象1時,會是的test1()和test2()都處於業務傍邊;test1()處於景象2時,就會拋反常,可是這個時分test2()不能夠提交,可是test1()卻是能夠成功提交的。此外,還有一點,留意上述test2()是處於另一個類中的,假如是處於同一個類,那麼PROPAGATION_MANDATORY不會因爲外層是不是有業務而拋反常。
4. PROPAGATION_REQUIRES_NEW: 老是敞開一個新的業務。假如一個業務現已存在,則將這個存在的業務掛起。
Java代碼 保藏代碼
//景象1:PROPAGATION_REQUIRED業務特點 景象2:不配任何業務特點 
public void test1() throws Exception{ 
avInfoTaskTunnel.insertAvInfoTask(); 
otherService.test2(); 

//otherService的test2()裝備PROPAGATION_REQUIRES_NEW業務特點 
public void test2() throws Exception { 
avRequestTunnel.insertAvRequest(); 
throw new Exception(); 

上述狀況,test1()處於景象2時test2()新建業務,這點沒有疑問。那假如test1()處於景象1呢?也即是說test1()現已有業務了。成果是test2()處於新的業務中,怎樣確定是處於新的業務中呢?看下面代碼:
Java代碼 保藏代碼
//test1裝備PROPAGATION_REQUIRED業務特點 
public void test1() throws Exception{ 
avInfoTaskTunnel.insertAvInfoTask(); 
otherService.test2(); //PROPAGATION_REQUIRES_NEW業務特點 


//otherService.test2() 
public void test2() throws Exception{ 
avRequestTunnel.insertAvRequest(); 
throw new Exception(); 

假如是在同一業務中,那麼景象將同於敘述PROPAGATION_REQUIRED特點時的景象,test1()和test2()都將回滾,而且拋出反常業務被打上rollback-only符號的反常。可是這兒,成果即是test2()回滾,test1正常提交,所以otherService.test2()處於新的業務中。留意:上述狀況test2()也是另一個類的辦法,假如歸於同一類,也即是test1()和test2()處於同一個類,test1()中調用test2(),那麼裝備的PROPAGATION_REQUIRES_NEW將無效(跟test2()啥業務特點都沒裝備相同)。可是假如是main函數中直接調用test2(),那麼仍是會起一個新的業務。
別的一種證實test1()和test2()處於不相同業務的辦法是,在test2()不拋出反常,然後再test1()調用了test2()以後,拋出反常,最後成果是()回滾,test2()正常提交。

5. PROPAGATION_NOT_SUPPORTED: 老對錯業務地履行,並掛起任何存在的業務。
Java代碼 保藏代碼
//test1裝備PROPAGATION_REQUIRED業務特點 
public void test1() throws Exception{ 
avInfoTaskTunnel.insertAvInfoTask(); 
otherService.test2(); //PROPAGATION_NOT_SUPPORTED業務特點 


//otherService.test2() 
public void test2() throws Exception{ 
avRequestTunnel.insertAvRequest(); 
throw new Exception(); 

假如otherService.test2() 沒有裝備業務特點,那麼test2()拋出反常時,test1()和test2()都回滾。可是如今test2()裝備了PROPAGATION_NOT_SUPPORTED業務特點,那麼test2()將以非業務運轉,而test1()持續運轉在業務中,也即是說,此刻,test1()回滾,test2()正常提交。留意:假如test1()和test2()在同一類中,那麼test2()的PROPAGATION_NOT_SUPPORTED失效。

6. PROPAGATION_NEVER: 老對錯業務地履行,假如存在一個活動業務,則拋出反常
Java代碼 保藏代碼
//test1裝備PROPAGATION_REQUIRED業務特點 
public void test1() throws Exception{ 
avInfoTaskTunnel.insertAvInfoTask(); 
otherService.test2(); //PROPAGATION_NEVER業務特點 


//otherService.test2() 
public void test2() throws Exception{ 
avRequestTunnel.insertAvRequest(); 
throw new Exception(); 

//test1()裝備PROPAGATION_REQUIRED業務特點, otherService.test2()裝備PROPAGATION_NEVER業務特點,將拋下面反常: 
org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never' 
當然上述狀況,假如是test1()和test2()在同一類中,那麼PROPAGATION_NEVER也將失效。

7. PROPAGATION_NESTED:假如一個活動的業務存在,則運轉在一個嵌套的業務中. 假如沒有活動業務, 則按TransactionDefinition.PROPAGATION_REQUIRED 特點履行
最簡單弄混雜的本來是 PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED。PROPAGATION_REQUIRES_NEW 發動一個新的, 不依賴於環境的 "內部" 業務. 這個業務將被徹底 commited 或 rolled back 而不依賴於外部業務, 它擁有自個的阻隔規模, 自個的鎖, 等等. 當內部業務開端履行時, 外部業務將被掛起, 內務業務完畢時, 外部業務將持續履行。另一方面, PROPAGATION_NESTED 開端一個 "嵌套的" 業務, 它是現已存在業務的一個真實的子業務. 嵌套業務開端履行時, 它將獲得一個 savepoint. 假如這個嵌套業務失利, 咱們將回滾到此 savepoint.。嵌套業務是外部業務的一部分, 只要外部業務完畢後它纔會被提交。由此可見, PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大差異在於, PROPAGATION_REQUIRES_NEW 徹底是一個新的業務, 而 PROPAGATION_NESTED 則是外部業務的子業務, 假如外部業務 commit, 潛套業務也會被 commit, 這個規矩相同適用於 roll back.
Java代碼 保藏代碼
//test1裝備PROPAGATION_REQUIRED業務特點 
public void test1() throws Exception{ 
avInfoTaskTunnel.insertAvInfoTask(); 
otherService.test2(); //PROPAGATION_NESTED業務特點 


//otherService.test2() 
public void test2() throws Exception{ 
avRequestTunnel.insertAvRequest(); 

上述狀況,假如otherService.test2()裝備PROPAGATION_REQUIRES_NEW業務特點,這樣test1()回滾,可是test2()正常提交,因爲這是兩個業務。可是假如otherService.test2()裝備PROPAGATION_NESTED業務特點,那麼test1()和test2()都將回滾。


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