一、场景:
事务的传播行为一般发生在事务嵌套的场景中。如:有一个事务的方法里面调用了另外一个有事务的方法。这时会产生事务边界控制问题。即两个方式是各自作为事务提交还是内层事务合并到外层事务一起提交。
spring规定了七大传播机制来季节当前事务控制问题。
二、传播机制
传播机制 | 说明 |
---|---|
PROPAGATION_REQUIRED | 如果当前没有事务,就创建一个事务,如果已经存在事务,就加入到这个事务。当前传播机制也是spring默认传播机制 |
PROPAGATION_REQUIRES_NEW | 新建事务,如果当前存在事务,就抛出异常。 |
PROPAGATION_SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
PROPAGATION_MANDATORY | 使用当前的事务,如果当前没有事务,就抛出异常 |
PROPAGATION_NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常。 |
PROPAGATION_NESTED | 如果当前存在事务,则在嵌套的事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作 |
三、举例
1、PROPAGATION_REQUIRED
若当前存在事务,则加入该事务,若不存在事务,则新建一个事务。
class Test1(){
@Transactional(propagation = Propagation.REQUIRED)
function A(){
T2.B();
}
}
class T2(){
@Transactional(propagation = Propagation.REQUIRED)
function B(){
System.out.println("T2 的 B 方法被调用");
}
}
1)、若B方法抛出异常,A方法进行捕获,A会抛出异常,因为T2标志回滚,T1标志提交,产生冲突。(若希望A不抛出异常则需要在A的catch中添加,类似如下代码)
function A(){
...
try{
...
...
T2.B();
}catch(Exception e){
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
e.printStackTrace();
}
}
2)、若B方法抛出异常,B方法内部捕获,A、B都不会回滚。(但如果B抛出异常的同时B方法内部捕获,并且B自己设置回滚【TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();】,
那么A和B都会回滚。)
3、若A或B抛出异常,但都没有捕获,则A、B都回滚。
4、A、B可操作同一条记录,因为处于同一个事务中。
2、PROPAGATION_REQUIRES_NEW
若当前没有事务,则新建一个事务。若当前存在事务,则新建一个事务,新老事务相互独立。外部事务抛出异常回滚不会影响内部事务的正常提交。
class C1(){
@Transactional(propagation = Propagation.REQUIRED)
function A(){
C2.B();
}
}
class C2(){
@Transactional(propagation = Propagation.REQUIRE_NEW)
function B(){
do something;
}
}
1)、若B方法抛出异常,A方法进行捕获,B方法回滚,A方法不受B异常影响。若B方法抛出异常,A方法进行捕获,且A方法设置对B方法的异常回滚,那么A、B方法都回滚。
2)、若B方法抛出异常,B方法内部捕获,A、B都不会回滚。若B方法抛出异常,B方法内部捕获,且B方式设置回滚。那么B方法回滚,A方法继续提交事务。
3)、若A方法抛出异常,A自行捕获,不会影响B正常执行,且AB都提交事务。若A捕获且设置回滚,那么A回滚事务,B正常提交事务。
4)、若B方法抛出异常,A、B方法都没有处理,则A、B都会回滚。
5)、A、B不可操作同一条记录,因为处于不同事务中,会产生死锁。
3、PROPAGATION_NESTED
如果当前存在事务,则嵌套在当前事务中执行。如果当前没有事务,则新建一个事务,类似于REQUIRE_NEW。
class C1(){
@Transactional(propagation = Propagation.REQUIRED)
function A(){
C2.B();
}
}
class C2(){
@Transactional(propagation = Propagation.NESTED)
function B(){
do something;
}
}
1)、若B方法抛出异常,A方法进行捕获,B方法回滚,A方法正常执行。若B方法抛出异常且捕获异常,则AB都不会提交
2)、若A或者B抛出异常,不做任何处理的话,A、B都要回滚。
3)、A、B可操作同一条记录,因为处于同一个事务中。
4、PROPAGATION_SUPPORTS
支持当前事务,若当前不存在事务,以非事务的方式执行。
5、PROPAGATION_NOT_SUPPORTED
以非事务的方式执行,若当前存在事务,则把当前事务挂起。
class C1(){
@Transactional(propagation = Propagation.REQUIRED)
function A(){
C2.B();
}
}
class C2(){
@Transactional(propagation = Propagation.NOT_SUPPORTED)
function B(){
do something;
}
}
A、B不可操作同一条记录,因为A是事务执行,B在A尚未提交前再操作同一条记录,会产生死锁。
6、PROPAGATION_MANDATORY
强制事务执行,若当前不存在事务,则抛出异常
7、PROPAGATION_NEVER
以非事务的方式执行,如果当前存在事务,则抛出异常。
也可以参考该网站信息:
https://www.cnblogs.com/rookie--/p/14710821.html