多个事务的⽅法相互调⽤时,事务如何在这些⽅法间传播,⽅法A是⼀个事务的⽅法,⽅法A执⾏过程中调⽤了⽅法B,那么⽅法B有没有事务以及⽅法B对事务的要求不同都会对⽅法A的事务具体执⾏造成影响,同时⽅法A的事务对⽅法B的事务执⾏也有影响,这种影响具体是什么就由两个⽅法所定义的事务传播类型所决定。
事务传播类型 | 当前存在事务 | 当前没有事务 |
---|---|---|
REQUIRED(Spring默认的事务传播类型) | 加⼊当前事务 | 新建⼀个事务 |
SUPPORTS | 加⼊当前事务 | 以⾮事务⽅法执⾏ |
MANDATORY | 加⼊当前事务 | 抛出异常 |
REQUIRES_NEW | 挂起该事务 | 新建⼀个事务 |
NOT_SUPPORTED | 挂起该事务 | 以⾮事务⽅法执⾏ |
NEVER | 抛出异常(不使⽤事务) | |
NESTED(嵌套的) | 在嵌套事务中执⾏(创建当前事务的子事务(嵌套事务),子事务不能单独提交,只能和父事务一起提交) | 和REQUIRED的操作⼀样(新建⼀个事务) |
//区别对比:
//1、REQUIRED(默认的传播机制):
method a(){
b();
c(); }
@Transactional(propagation = Propagation.REQUIRED)
method b(){
insert(B); //插入一条数据B
}
@Transactional(propagation = Propagation.REQUIRED)
method c(){
insert(C); //插入一条数据C
throw new Exception("抛一个异常");
}
/*说明:
执行方法a()时,由于当前没有事务,则新建了一个事务A。
执行方法b()时,由于当前存在事务A,则加入事务A,数据B插入成功,但插入数据B的事务A还未提交。
执行方法c()时,由于当前存在事务A,则加入事务A,数据C插入后抛异常,回滚事务A。
结果:数据B插入失败,数据C插入失败。*/
//2、REQUIRES_NEW:
method a(){
b();
c(); }
@Transactional(propagation = Propagation.REQUIRES_NEW)
method b(){
insert(B); //插入一条数据B
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
method c(){
insert(C); //插入一条数据C
throw new Exception("抛一个异常");
}
/*说明:
执行方法a()时,由于当前没有事务,则新建了一个事务A。
执行方法b()时,由于当前存在事务A,则把事务A挂起,新建一个事务B,数据B插入成功,事务B提交。
执行方法c()时,由于当前存在事务A,则把事务A挂起,新建一个事务C,数据C插入成功后抛异常,事务C回滚,数据C插入失败后不会影响数据B。
结果:数据B插入成功,数据C插入失败。*/
//3、NESTED:
method a(){
b();
c(); }
@Transactional(propagation = Propagation.NESTED)
method b(){
insert(B); //插入一条数据B
}
@Transactional(propagation = Propagation.NESTED)
method c(){
insert(C); //插入一条数据C
throw new Exception("抛一个异常");
}
/*说明:
执行方法a()时,由于当前没有事务,则新建了一个事务A。
执行方法b()时,由于当前存在事务A,则创建一个当前事务的子事务AB,数据B插入成功,此时子事务还未提交,待父事务A提交时才会提交子事务AB。
执行方法c()时,由于当前存在事务A,则创建一个当前事务的子事务AC,数据C插入后抛异常,子事务AC抛异常,待父事务A提交时才回滚。
提交父事务A,提交子事务AB,回滚子事务AC。
结果:数据B插入成功,数据C插入失败。*/