Java Web —— 第九天(事务)

事务管理 & AOP

事务回顾

概念

事务 是一组操作的集合,它是一个不可分割的工作单位,这些操作 要么同时成功,要么同时失败

操作

开启事务(一组操作开始前,开启事务): start transaction / begin

提交事务(这组操作全部成功后,提交事务):commit 

回滚事务(中间任何一个操作出现异常,回滚事务): rollback 

@Transactional

@Transactional 是 Spring 框架中用于声明事务的注解,它可以应用在方法或类上,定义该方法或类中的所有方法在执行时应该运行在一个事务中。通过使用 @Transactional,可以确保数据库操作的一致性和数据的完整性,即使在出现异常时也可以回滚操作。

@Transactional基本用法
  • 方法级别: 当 @Transactional 注解应用在方法上时,该方法的所有数据库操作都会在一个事务中执行。
  • 类级别: 当 @Transactional 注解应用在类上时,该类的所有公共方法都会在一个事务中执行。

案例

解散部门:删除部门,同时删除该部门下的员工

//删除
    @Transactional //spring事务管理
    @Override
    public void DeleteDept(Integer id) {
        deptMapper.DeleteDept(id); //根据id删除部门数据
        //int i = 3/0; 异常,删除的部门数据会通过事务回滚恢复
        empMapper.deleteByDeptId(id); //根据被删除的部门id 删除该部门下的员工
    }
    //根据部门id删除部门下的员工数据
    @Delete("delete from emp where dept_id = #{deptId}")
    void deleteByDeptId(Integer deptId);
Spring事务管理

注解:@Transactional

位置:业务(service)层的方法上、类上、接口上

作用:将当前方法交给spring进行事务管理,方法执行前,开启事务,成功执行完毕,提交事务,

出现异常,回滚事务

事务进阶

rollbackFor

事务属性-回滚

默认情况下,只有出现 RuntimeException才回滚异常。rollbackFor属性用于控制出现何种异常类型,回滚事务

     //删除
    @Transactional(rollbackFor = Exception.class) //spring事务管理
    @Override
    public void DeleteDept(Integer id) {
        deptMapper.DeleteDept(id); //根据id删除部门数据
        //int i = 3/0; 异常,删除的部门数据会通过事务回滚恢复
        empMapper.deleteByDeptId(id); //根据被删除的部门id 删除该部门下的员工
    }

propagation

事务属性-传播行为

事务传播行为:指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行事务控制

Java Web —— 第九天(事务)_第1张图片

案例

解散部门时,记录操作日志

需求:解散部门时,无论是成功还是失败,都要记录操作日志步骤:

1.解散部门:删除部门、删除部门下的员工


    //删除
    @Transactional(rollbackFor = Exception.class) //spring事务管理
    @Override
    public void DeleteDept(Integer id) {
        try {
            deptMapper.DeleteDept(id); //根据id删除部门数据
//            int i = 3/0; //异常,删除的部门数据会通过事务回滚恢复
            empMapper.deleteByDeptId(id); //根据被删除的部门id 删除该部门下的员工
        } finally { //无论上面代码成功或失败都会执行
            DeptLog deptLog = new DeptLog();
            deptLog.setCreateTime(LocalDateTime.now());
            deptLog.setDescription("执行了解散部门的操作,解散的部门id是:"+id);
            deptLogService.insert(deptLog);
        }

    }

2.记录日志到数据库表中 

@Service
public class DeptLogServiceImpl implements DeptLogService {

    @Autowired
    private DeptLogMapper deptLogMapper;

    @Transactional(propagation = Propagation.REQUIRES_NEW)//调用insert方法时,会开启一个新的事务
    @Override
    public void insert(DeptLog deptLog) {
        deptLogMapper.insert(deptLog);
    }

 场景

REQUIRED:大部分情况下都是用该传播行为即可。

REQUIRES_NEW:当我们不希望事务之间相互影响时,可以使用该传播行为。比如:下订单前需要记录日志,不论订单保存成功与否,都需要保证日志记录能够记录成功

AI扩展

在Spring事务管理中,REQUIREDREQUIRES_NEW 是两种常见的事务传播行为,它们主要用于控制在方法调用过程中事务的传播方式。

1. REQUIRED 传播行为

  • 概念: REQUIRED 是默认的传播行为,它表示当前方法需要在一个已有的事务中执行。如果调用方已经在一个事务中,当前方法将加入到这个事务中;如果没有,Spring 会创建一个新的事务。
  • 适用场景: REQUIRED 适用于大多数情况下,因为它能确保整个业务逻辑在同一个事务中运行,这样如果在事务中的某个方法抛出了异常,整个事务会回滚,保证数据的一致性。
@Transactional(propagation = Propagation.REQUIRED)
public void updateAccount() {
    // 如果调用者已经有事务,加入现有事务;否则创建新事务
}

2. REQUIRES_NEW 传播行为

  • 概念: REQUIRES_NEW 表示当前方法总是需要一个新的事务。无论调用方是否有事务,Spring 都会为这个方法创建一个新的事务,并且暂停调用方的事务,直到新事务完成。如果新事务回滚,不会影响调用方的事务。
  • 适用场景: REQUIRES_NEW 常用于需要隔离的操作。例如,在一个大事务中,需要确保某个操作(如日志记录或事件追踪)独立于主要事务,即使主要事务回滚,也要保证这些操作能够成功完成。
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveLog() {
    // 始终启动一个新事务,暂停外部事务
}

扩展理解

在一个复杂的业务逻辑中,多个服务或方法之间的调用可能会有不同的事务处理需求。使用 REQUIRES_NEW 时,新的事务独立于外部事务,因此即使外部事务失败回滚,REQUIRES_NEW 包含的操作仍然会成功提交。

举例

假设在一个订单系统中,用户下订单时需要先记录操作日志。此时,saveLog 方法使用 REQUIRES_NEW,即使订单提交失败,日志也会被成功保存。这对于追踪失败原因、审计记录等场景非常有用。

@Transactional(propagation = Propagation.REQUIRED)
public void placeOrder(Order order) {
    // 记录订单日志,独立事务
    saveLog(order);

    // 下订单,主事务
    saveOrder(order);
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveLog(Order order) {
    // 记录日志,确保独立于主事务,即使主事务回滚,日志也会被保存
}

在上述代码中,即使 saveOrder 发生异常并导致订单提交失败,saveLog 的日志记录也不会受到影响,这样可以确保日志记录的完整性。

你可能感兴趣的:(java,开发语言)