springboot事务操作

事务操作

事务处理就是将一个方法中的全部操作当初一个整体,如果其中一个地方报出异常,我们就需要回滚回之前的操作,防止数据混乱,数据缺失

1、@Transactional

springboot为我们提供了@Transactional注解,该注解可以用于管理一个方法,一个类,一个接口,但是我们一般只使用它来管理一个方法即可,因为需要用到事务操作的一般也就是增删改这些操作

该注释在方法开始前会开启事务,在函数末尾会提交/回滚事务

2、事务传播

事务传播简单理解就是我对一个方法使用创建了一个事务,但是呢,该方法里面的一个函数同样创建了一个事务,这时我们就需要考虑合并为一个事务,还是分别是独立的事务等问题

springboot提供了事务的一系列操作

其中,我们只需要重点关注两个属性

假设这里有两个函数,函数A和函数B,函数A里面调用了函数B,假设两个都有事务

  • REQUIRED 这个为Transactional的默认值,如果函数A有创建事务,那么函数B归并到函数A的事务中,如果函数A回滚了,那么函数B的操作也回滚
  • REQUIRES_NEW:这个与REQUIRED不同,两个事务互为独立事务,即使函数A回滚了,但是函数B实现的操作不会回滚,听起来很鸡肋是吧,不会滚我还使用事务干嘛,别急,下面就举例场景

在这个场景中,无论解散部门成功与否都需要将日记记录下来,这里我们将记录日记的操作理解为上述的函数B的操作,删除部门的操作为函数A的操作

相关函数实现

  • 函数A
java 复制代码
    @Transactional
    @Override
    public void deleteDeptById(Integer id) {
        try {
            deptMapper.deleteDeptById(id);
            // 删除部门后,将部门的所有员工删除
            int i = 1 / 0;//我们设计一个异常的情况
            empMapper.deleteEmpsByDeptId(id);
            // 无论是否删除成功 都要添加日记到数据库表中

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

    }
  • 函数B

    java 复制代码
        @Transactional(propagation = Propagation.REQUIRES_NEW)
        @Override
        public void insert(DeptLog deptLog) {
            deptLogMapper.insert(deptLog);
        }

让我们分析一下,如果使用REQUIRED的情况,我们将函数A和函数B合并到一个事务(函数A的事务中),这时,在执行int i = 1 / 0;时报出了一个错误,那么函数A的事务必须回滚,即使函数B在finally中已经写好了数据,但还是没有,照样回滚,日记没有写入到数据表中,如果我们使用REQUIRES_NEW,A和B是两个独立的事务,在调用函数B时,函数A的事务被挂起,如果函数B执行成功并提交,即使抛出异常导致外层事务回滚,函数B的事务也不会回滚,意思就是说函数a回滚的范围并不包括函数b。

这里我们可以看出,事务的回滚并不是一定要回滚全部操作,我认为使用事务回滚的重要原因是:只有缺乏某方法会导致数据异常,导致数据混乱时才有必要使用回滚,如果某方法与主事务的数据毫不相干,互相独立,就没有必要进行回滚,这与事务回滚的初衷相符且增加了事务回滚的灵活性,所以REQUIRES_NEW的出现我觉得是非常合理的

从这里我们也可以看出使用REQUIRES_NEW的场景

​ 使用 REQUIRES_NEW 时,需要确保新事务中的操作不会对主事务中的操作产生冲突或导致数据不一致。这通常意味着新事务中的操作是独立的、只读的或与主事务操作无关。

3、事务回滚的注意事项

@Transactional事务回滚默认只回滚RuntimeException异常(运行时异常),其他异常不会回滚,我们需要设定@Transactional的rollbackFor来回滚所有异常

java 复制代码
    // Transactional 事务管理
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteDeptById(Integer id) {
        try {
            deptMapper.deleteDeptById(id);
            // 删除部门后,将部门的所有员工删除
            empMapper.deleteEmpsByDeptId(id);
            // 无论是否删除成功 都要添加日记到数据库表中

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

    }
相关推荐
Asthenia04123 分钟前
RocketMQ 消息不丢失与持久化机制详解-生产者与Broker之间的详解
后端
〆、风神32 分钟前
Spring Boot 整合 Lock4j + Redisson 实现分布式锁实战
spring boot·分布式·后端
Asthenia041235 分钟前
Select、Poll、Epoll 详细分析与面试深度剖析/C代码详解
后端
烛阴38 分钟前
Node.js中必备的中间件大全:提升性能、安全与开发效率的秘密武器
javascript·后端·express
南雨北斗42 分钟前
WMware虚拟机下载方法(2025年4月)
后端
朝阳5811 小时前
Rust项目GPG签名配置指南
开发语言·后端·rust
微网兔子1 小时前
伺服器用什么语言开发呢?做什么用什么?
服务器·c++·后端·游戏
朝阳5811 小时前
Rust实现高性能目录扫描工具ll的技术解析
开发语言·后端·rust
橘猫云计算机设计1 小时前
springboot基于hadoop的酷狗音乐爬虫大数据分析可视化系统(源码+lw+部署文档+讲解),源码可白嫖!
数据库·hadoop·spring boot·爬虫·python·数据分析·毕业设计
小希爸爸1 小时前
2、中医基础入门和养生
前端·后端