首页 > 代码库 > spring事务声明的几种传播特性

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()都将回滚。


spring事务声明的几种传播特性