一、什么是事务传播行为?事务传播行为(propagation behavior)指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何运行 。
例如:methodA方法调用methodB方法时,methodB是继续在调用者methodA的事务中运行呢 , 还是为自己开启一个新事务运行 , 这就是由methodB的事务传播行为决定的 。
二、事务传播行为类型Spring在TransactionDefinition接口中规定了7种类型的事务传播行为 。事务传播行为是Spring框架独有的事务增强特性,这是Spring为我们提供的强大的工具箱,使用事务传播行为可以为我们的开发工作提供许多便利 。
两大类
- 支持事务的传播
- 不支持事物的传播
- REQUIRED:(支持事务)如果当前没有事务 , 就创建一个新事务,如果当前存在事务 , 就加入该事务(Spring默认)
- SUPPORTS:(支持事务)如果当前存在事务,就加入该事务 , 如果当前不存在事务 , 就以非事务执行
- MANDATORY:(支持事务)如果当前存在事务,就加入该事务 , 如果当前不存在事务,就抛出异常
- REQUIRES_NEW:(支持事务)创建新事务,无论当前存不存在事务,都创建新事务
- NOT_SUPPORTED:(不支持事务)如果当前存在事务,就把当前事务挂起
- NEVER:(不支持事务)以非事务方式执行,如果当前存在事务 , 则抛出异常
- NESTED:(支持事务)如果当前存在事务,则在嵌套事务内执行 。如果当前没有事务 , 就创建一个新事务
CREATE TABLE `ks_a` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id',`name` varchar(20) DEFAULT NULL COMMENT '姓名',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='测试A';CREATE TABLE `ks_b` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id',`age` tinyint(4) DEFAULT NULL COMMENT '年龄',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='测试B';
1、REQUIRED1.1、父方法无事务,子方法开启事务,子方法报错 public void add() {KsA ksA = new KsA();ksA.setName("林");ksAService.insert(ksA);KsB ksB = new KsB();ksB.setAge(10);ksBService.insertError(ksB); }
@Transactional(propagation = Propagation.REQUIRED) public void insertError(KsB ksB) {ksBDao.insert(ksB);throw new RuntimeException("子方法报错"); }
结果:ks_a数据插入成功,ks_b数据回滚文章插图
文章插图
1.2、父方法开启事务,子方法开启事务,父方法报错
@Transactional public void add() {KsA ksA = new KsA();ksA.setName("林");ksAService.insert(ksA);KsB ksB = new KsB();ksB.setAge(10);ksBService.insert(ksB);throw new RuntimeException("主方法报错"); }
@Transactional(propagation = Propagation.REQUIRED) public void insert(KsB ksB) {ksBDao.insert(ksB); }
结果:两表数据都回滚了文章插图
文章插图
1.3、父方法开启事务,子方法开启事务,子方法报错
@Transactional public void add() {KsA ksA = new KsA();ksA.setName("林");ksAService.insert(ksA);KsB ksB = new KsB();ksB.setAge(10);ksBService.insertError(ksB); }
@Transactional(propagation = Propagation.REQUIRED) public void insertError(KsB ksB) {ksBDao.insert(ksB);throw new RuntimeException("子方法报错"); }
结果:两表数据都回滚了文章插图
文章插图
总结父方法无事务,子方法开启新事务父方法有事务,子方法和父方法共用一个事务(无论父、子方法报错,整体回滚)
2、SUPPORTS2.1、父方法无事务,子方法开启事务,子方法报错
public void add() {KsA ksA = new KsA();ksA.setName("林");ksAService.insert(ksA);KsB ksB = new KsB();ksB.setAge(10);ksBService.insertError(ksB); }
@Transactional(propagation = Propagation.SUPPORTS) public void insertError(KsB ksB) {ksBDao.insert(ksB);throw new RuntimeException("子方法报错"); }
结果:数据都插入成功文章插图
推荐阅读
- 四十八 SpringCloud微服务实战——搭建企业级开发框架:【移动开发】整合uni-app搭建移动端快速开发框架-使用第三方UI框架
- Spring Retry 重试
- SpringBoot自定义注解+异步+观察者模式实现业务日志保存
- 装配 SpringBoot自动配置流程
- Seata 环境搭建
- 四十七 SpringCloud微服务实战——搭建企业级开发框架:【移动开发】整合uni-app搭建移动端快速开发框架-添加Axios并实现登录功能
- SpringCloud怎么迈向云原生?
- Filter Spring中过滤器和拦截器(Interceptor)的区别和联系
- 二 SpringCloud - Eureka注册中心,feign远程调用,hystrix降级和熔断
- 二 【SSM】学习笔记——SpringMVC入门