JavaWeb——事务管理(3/3)-事务进阶-propagation属性(事务的传播行为、应用场景、高亮显示的插件、测试演示、总结)

目录

事务进阶:Propagation 属性

1. 事务的传播行为(Propagation)

2. Propagation 属性的几种类型

3. 事务传播行为的应用场景

4. Propagation 的使用示例

4.1 部门操作日志表

4.2 部门操作日志类 

4.3 DeptLogMapper

4.4 DeptLogService 

4.5 DeptService

4.6 安装高亮显示的插件

4.7 演示默认配置 

4.8 演示修改配置

5. Propagation 使用建议

总结


事务进阶:Propagation 属性

1. 事务的传播行为(Propagation)

        在 Spring 事务管理中,Propagation(传播行为)用于控制事务方法在调用另一个事务方法时应该如何处理事务。

2. Propagation 属性的几种类型

Spring 提供了 7 种事务传播行为,分别如下:

传播行为描述
REQUIRED(默认值)如果当前存在事务,则加入该事务;否则创建一个新的事务。
REQUIRES_NEW无论当前是否有事务,都会创建一个新的事务,新的事务独立于已有事务。
SUPPORTS如果当前存在事务,则加入该事务;如果没有事务,则以非事务方式运行。
NOT_SUPPORTED以非事务方式运行,如果当前存在事务,则挂起事务。
MANDATORY必须在一个已有事务中运行,如果当前没有事务,则抛出异常。
NEVER必须以非事务方式运行,如果当前存在事务,则抛出异常。
NESTED如果当前存在事务,则创建一个嵌套事务(内层事务可以独立回滚);如果没有事务,则等同于 REQUIRED。

3. 事务传播行为的应用场景

  1. REQUIRED(默认值)

    • 适用于大部分场景,如Service 方法默认采用 REQUIRED,确保调用链上的事务一致。

    • 例如:

      @Transactional(propagation = Propagation.REQUIRED)
      public void methodA() {
          methodB();
      }
      
      • methodA() 调用 methodB(),两者属于同一个事务。

  2. REQUIRES_NEW

    • 适用于需要独立提交或回滚的操作,如日志记录:

      @Transactional(propagation = Propagation.REQUIRES_NEW)
      public void saveLog() {
          // 日志存储
      }
      
      • saveLog() 独立于调用者的事务,即使主事务回滚,日志也会被保存。

  3. SUPPORTS

    • 适用于既可以在事务环境下执行,也可以在非事务环境下执行的操作:

      @Transactional(propagation = Propagation.SUPPORTS)
      public void methodC() {
          // 可选事务支持
      }
      
      • 如果 methodC() 由一个事务方法调用,则加入事务,否则以非事务方式执行。

  4. NOT_SUPPORTED

    • 适用于不希望事务影响某些操作,如执行非事务性的查询:

      @Transactional(propagation = Propagation.NOT_SUPPORTED)
      public void methodD() {
          // 非事务方式运行
      }
      
      • methodD() 以非事务方式运行,即使调用它的方法有事务。

  5. MANDATORY

    • 适用于必须有事务的情况,如某些业务逻辑必须依赖事务:

      @Transactional(propagation = Propagation.MANDATORY)
      public void methodE() {
          // 需要事务支持,否则抛异常
      }
      
      • 如果 methodE() 在没有事务的情况下被调用,会抛出异常。

  6. NEVER

    • 适用于强制不使用事务的场景:

      @Transactional(propagation = Propagation.NEVER)
      public void methodF() {
          // 强制非事务运行
      }
      
      • 如果 methodF() 在事务中调用,会抛出异常。

  7. NESTED

    • 适用于子方法需要部分回滚但主事务不受影响

      @Transactional(propagation = Propagation.NESTED)
      public void methodG() {
          // 嵌套事务
      }
      
      • methodG() 创建一个嵌套事务,支持局部回滚


4. Propagation 的使用示例

先准备好日志表以及部门操作日志类

4.1 部门操作日志表

create table dept_log
(
    id          int auto_increment comment '主键ID' primary key,
    create_time datetime     null comment '操作时间',
    description varchar(300) null comment '操作描述'
) comment '部门操作日志表';

4.2 部门操作日志类 

@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeptLog {
    private Integer id;
    private LocalDateTime createTime;
    private String description;
}

4.3 DeptLogMapper

@Mapper
public interface DeptLogMapper {
    @Insert("insert into dept_log(create_time,description) values(#{createTime},#{description})")
    void insert(DeptLog log);
}

4.4 DeptLogService 

public interface DeptLogService {
    void insert(DeptLog deptLog);
}
@Service  // 标记为 Spring 管理的 Bean
public class DeptLogServiceImpl implements DeptLogService {

    @Autowired
    private DeptLogMapper deptLogMapper;

    @Transactional
    @Override
    public void insert(DeptLog deptLog) {
        deptLogMapper.insert(deptLog);
    }
}

4.5 DeptService

@Service
public class DeptServiceImpl implements DeptService {
    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private EmpMapper empMapper;
    @Autowired
    private DeptLogService deptLogService;

    /*
    删除部门
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(Integer id) {
        try {
            //1.删除部门
            deptMapper.deleteById(id);
            int i = 1/0;  //模拟抛出异常
            // if(true){throw new Exception("出错啦!")}

            //2.根据部门id,删除部门下的员工信息
            empMapper.deleteByDeptId(id);

        } finally {
            DeptLog deptLog = new DeptLog();
            deptLog.setCreateTime(LocalDateTime.now());
            deptLog.setDescription("执行了解散部门的操作,此次解散的是" + id + "号部门");
            deptLogService.insert(deptLog);
        }
    }

}

4.6 安装高亮显示的插件

安装好之后重启一下IDEA

4.7 演示默认配置 

发送删除部门请求,查看后台并标记高亮显示:

部门操作记录表没有变化:

4.8 演示修改配置

这时我们需要修改日志事务的传播行为,解散部门时,无论是成功还是失败,都要记录操作日志。 

重新运行项目,再次发送删除部门请求。

这次即使删除的事务回滚了,日志记录的事务也没有回滚了:

5. Propagation 使用建议

  • 一般业务逻辑:使用 REQUIRED,保持事务一致性。

  • 日志等独立操作:使用 REQUIRES_NEW,避免事务回滚影响日志。

  • 查询操作:使用 SUPPORTSNOT_SUPPORTED,减少事务开销。

  • 事务强制要求:使用 MANDATORY,确保在事务上下文执行。

  • 严格禁止事务:使用 NEVER,确保操作不受事务管理。

  • 局部回滚需求:使用 NESTED,保证子事务可回滚但不影响主事务。


总结

  • Propagation 控制方法之间事务的传播方式,影响事务的创建、加入、挂起等行为。

  • 选择合适的传播行为可提升事务控制的灵活性,优化事务管理策略。

  • 开发中,大多数情况使用 REQUIRED,日志等独立操作可使用 REQUIRES_NEW


END


学习自:黑马程序员——JavaWeb课程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值