spring事务传播机制
事务是我们开发中经常用到的,那么spring中的事务是怎么样的呢?可以用注解@Transactional注解来进行对spring事务的管理,注意:@Transactional注解只能放在public方法上面。他有一个Propagation属性,是用来控制事务的传播属性,主要有如下七个属性。
1.REQUIRED,这个是默认的属性
Support a current transaction, create a new one if none exists.
支持当前事务,如果当前没有事务,则新建事务。
如果当前存在事务,则加入当前事务,合并成一个事务。
2.MANDATORY
Support a current transaction, throw an exception if none exists.
支持当前事务,如果当前没有事务,就抛出异常。
3.NEVER
Execute non-transactionally, throw an exception if a transaction exists.
以非事务方式执行,如果当前存在事务,则抛出异常。
4.NOT_SUPPORTED
Execute non-transactionally, suspend the current transaction if one exists.
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
5.REQUIRES_NEW
Create a new transaction, suspend the current transaction if one exists.
新建事务,如果当前存在事务,把当前事务挂起。
6.SUPPORTS
Support a current transaction, execute non-transactionally if none exists.
支持当前事务,如果当前没有事务,就以非事务方式执行。
7.NESTED
Execute within a nested transaction if a current transaction exists, behave like PROPAGATION_REQUIRED else.
存在事务则运行在嵌套事务中,不存在则创建一个事务。
嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。
其中比较难理解的就是NOT_SUPPORTED 和NESTED ,现举个例子如下:
如果ServiceA.methodA的事务级别是PROPAGATION_REQUIRED,
package com.haoqiangwang.service; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; @Service public class ServiceA { @Resource private ServiceB serviceB; @Transactional(propagation = Propagation.REQUIRED) public void methodA(){ serviceB.methodB(); } }
而ServiceB.methodB的事务级别是PROPAGATION_NOT_SUPPORTED ,
package com.haoqiangwang.service; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @Service public class ServiceB { @Transactional(propagation = Propagation.NOT_SUPPORTED) public void methodB(){ //此时方法以非事务的状态运行 } }
那么当执行到ServiceB.methodB时,ServiceA.methodA的事务挂起,而他以非事务的状态运行完,再继续ServiceA.methodA的事务。
而ServiceB.methodB的事务级别为PROPAGATION_NESTED,
package com.haoqiangwang.service; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @Service public class ServiceB { @Transactional(propagation = Propagation.NESTED) public void methodB(){ //此时方法以新的事务的状态运行,此事务是调用它事务的子事务 } }
那么当执行到ServiceB.methodB的时候,ServiceA.methodA所在的事务就会挂起,ServiceB.methodB会起一个新的子事务并设置savepoint,等待ServiceB.methodB的事务完成以后,他才继续执行。因为ServiceB.methodB是外部事务的子事务,那么
1、如果ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚,ServiceB.methodB也将回滚。
2、如果ServiceB.methodB失败回滚,如果他抛出的异常被ServiceA.methodA的try..catch捕获并处理,ServiceA.methodA事务仍然可能提交;如果他抛出的异常未被ServiceA.methodA捕获处理,ServiceA.methodA事务将回滚。