Spring事务传播行为实战

一、什么是事务传播行为?事务传播行为(propagation behavior)指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何运行 。
例如:methodA方法调用methodB方法时,methodB是继续在调用者methodA的事务中运行呢 , 还是为自己开启一个新事务运行 , 这就是由methodB的事务传播行为决定的 。
二、事务传播行为类型Spring在TransactionDefinition接口中规定了7种类型的事务传播行为 。事务传播行为是Spring框架独有的事务增强特性,这是Spring为我们提供的强大的工具箱,使用事务传播行为可以为我们的开发工作提供许多便利 。
两大类

  • 支持事务的传播
  • 不支持事物的传播
七小种
  • REQUIRED:(支持事务)如果当前没有事务 , 就创建一个新事务,如果当前存在事务 , 就加入该事务(Spring默认)
  • SUPPORTS:(支持事务)如果当前存在事务,就加入该事务 , 如果当前不存在事务 , 就以非事务执行
  • MANDATORY:(支持事务)如果当前存在事务,就加入该事务 , 如果当前不存在事务,就抛出异常
  • REQUIRES_NEW:(支持事务)创建新事务,无论当前存不存在事务,都创建新事务
  • NOT_SUPPORTED:(不支持事务)如果当前存在事务,就把当前事务挂起
  • NEVER:(不支持事务)以非事务方式执行,如果当前存在事务 , 则抛出异常
  • NESTED:(支持事务)如果当前存在事务,则在嵌套事务内执行 。如果当前没有事务 , 就创建一个新事务
三、事务传播行为实战**说明:**父方法插入表ks_a、子方法插入表ks_b表结构:
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数据回滚
Spring事务传播行为实战

文章插图
Spring事务传播行为实战

文章插图
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); }结果:两表数据都回滚了
Spring事务传播行为实战

文章插图
Spring事务传播行为实战

文章插图
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("子方法报错"); }结果:两表数据都回滚了
Spring事务传播行为实战

文章插图
Spring事务传播行为实战

文章插图
总结父方法无事务,子方法开启新事务父方法有事务,子方法和父方法共用一个事务(无论父、子方法报错,整体回滚)
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("子方法报错"); }结果:数据都插入成功
Spring事务传播行为实战

文章插图
Spring事务传播行为实战

推荐阅读