Spring 事务的七种传播属性
1. 事务传播定义
事务传播机制定义了多个包含了事务的方法在相互调用时,事务是如何在这些方法之间进行传递的。
2. 作用
- 事务传播机制是解决一个事务在多个节点中传递的问题。
- 事务传播机制是保证一个事务在多个调用方法之间的可控性。
3. 七种传播属性
spring 提供了其中事务间的传播属性,如下表:
事务传播行为类型 |
说明 |
PROPAGATION_REQUIRED |
(默认事务)需要事务。若当前无事务,新建一个事务;若当前有事务,加入此事务中。 |
PROPAGATION_SUPPORTS |
支持事务。若当前没有事务,以非事务方式执行;若当前有事务,加入此事务中。 |
PROPAGATION_MANDATORY |
强制使用事务。若当前有事务,就使用当前事务;若当前没有事务,抛出异常。 |
PROPAGATION_REQUIRES_NEW |
新建事务。无论当前是否有事务,都新建事务运行。 |
PROPAGATION_NOT_SUPPORTED |
不支持事务。若当前存在事务,把当前事务挂起,然后运行方法。 |
PROPAGATION_NEVER |
不使用事务。若当前方法存在事务,则抛出异常,否则继续使用无事务机制运行。 |
PROPAGATION_NESTED |
嵌套。如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。 |
测试代码:
@Transactional
public void methodA() {
Course course = new Course();
Integer tId = 1;
String tName = "李老师";
course.setCName("英语");
course.setCId(1);
course.setTId(1);
courseMapper.insert(course);
try{
teacherService.methodB(tId, tName);
}catch (Exception e){
System.out.println(e.getCause());
}
// int i = 1/0;
}
@Transactional(propagation = Propagation.REQUIRED)
public void methodB( int tIdm, String name) {
Teacher teacher = new Teacher();
teacher.setTName(name);
teacher.setTId(tIdm);
teacherMapper.insert(teacher);
int i = 1/0;
}
3.1 PROPAGATION_REQUIRED
1) 调用者没有事务, 内部异常
测试结果如下图: 调用者数据插入成功,被调用者因为出现异常,发生回退,因此数据库无数据。
2) 调用者有事务, 内部异常
测试结果如下图: 调用者、被调用者数据插入失败, 内部事务异常,内外都回滚。两者属于同一个事务中。
3) 调用者有事务, 外部异常
测试结果如下图:调用者、被调用者数据插入失败, 外部事务异常,内外都回滚。两者属于同一个事务中。
3.2 PROPAGATION_SUPPORTS
1) 调用者没有事务, 内部异常
测试结果如下图: 调用者、被调用者数据插入成功,出现异常不回退。
2) 调用者有事务, 内部异常
测试结果如下图: 调用者、被调用者数据均插入失败回退。内部事务异常,内外都回滚。两者属于同一个事务中。
3)调用者有事务, 外部异常
测试结果如下图:调用者、被调用者数据插入失败, 外部事务异常,内外都回滚。两者属于同一个事务中。
3.3 PROPAGATION_MANDATORY
1) 调用者没有事务, 内部异常
测试结果如下图: 调用者数据插入成功,数据库查询没有事务。被调用者报错,“No existing transaction found for transaction marked with propagation 'mandatory”,插入失败
2)调用者有事务, 内部异常
测试结果如下图:效果同PROPAGATION_REQUIRED
3)调用者有事务, 外部异常
测试结果如下图:效果同PROPAGATION_REQUIRED
3.4 PROPAGATION_REQUIRES_NEW
1)调用者没有事务, 内部异常
测试结果如下图, 调用者成功插入数据,被调用者由于异常回退。
2)调用者有事务, 内部异常
测试结果如下图, 被调用者由于异常,事务回退。数据可可查内部无事务,外部事务不回退
3)调用者有事务, 外部异常
测试结果如下图,由于调用者和被调用者属于不通事务,因此调用者存现异常,被调用者不回滚
3.5 PROPAGATION_NOT_SUPPORTED
1)调用者没有事务, 内部异常
测试结果如下图, 均插入成功。
2)调用者有事务, 内部异常
测试结果如下图:均插入成功,被调用者无事务,不回退。
3)调用者有事务, 外部异常
测试结果如下图,外部出现异常,有事务, 调用者回滚。被调用者无事务不回滚,
3.6 PROPAGATION_NEVER
1)调用者没有事务, 内部异常
测试结果如下图, 均插入成功,均无事务
2)调用者有事务, 内部异常
测试结果如下图,调用者成功插入,被调用者报错Existing transaction found for transaction marked with propagation 'never', 插入失败
3)调用者有事务, 外部异常
测试结果如下图,调用者出现异常,回滚,被调用者报错Existing transaction found for transaction marked with propagation 'never', 插入失败
3.7 PROPAGATION_NESTED
1)调用者没有事务, 内部异常
执行与PROPAGATION_REQUIRED类似的操作
2)调用者有事务, 内部异常
测试结果如下图, 内部事务有异常回滚,外部事务不影响:
3)调用者有事务, 外部异常
测试结果如下图,外部出现异常,调用者和被调用者均回滚
4. 嵌套事务和加入事务的区别:
嵌套事务:回退有问题的事务,但主事务不受影响。外部事务回滚,内部事务也会被回滚;内部事务回滚,外部无问题,并不会回滚外部事务
加入事务:如果任意一个方法出现异常,那么整个事务会回滚。
参考:
https://blog.csdn.net/weixin_51367845/article/details/126216621
https://blog.csdn.net/fxkcsdn/article/details/107174742
https://baijiahao.baidu.com/s?id=1657492287327338765&wfr=spider&for=pc