spring boot 使用 mybatis 开启事务回滚 的总结

时间:2025-05-02 21:35:37

1.前言  

  以前没有使用mybatis,可以关闭自动提交,然后做sql操作,对操作进行catch捕获异常,

如果没有异常则commit 提交 ,有异常则 rollback 回滚,新增的数据则删除 ,修改的数据则修改回去,删除的则新增,

这就是事务操作。

  事务有四大特性

(1)原子性:要么全部执行成功,要么不执行。
(2)一致性:事务执行的结果,必须使数据库从一个一致性状态变到另一个一致性状态。
(3)隔离性:并发操作同一个表时数据库会开启多个事务,多个事务之间相互隔离。
(4)持久性:当事务确认完成后,对数据的改变是永久性的。

  那么mybatis怎么具体开启事务?

spring boot 开启其实很简单,使用注解开启即可,但是需要注意,需要触发非检查异常才会做事务回滚操作,【Exception 是检查异常】

但是如果使用try catch 捕获异常,也不会触发异常,因为异常被 吃下去了,做了服务降级操作,事务以为没有异常发生,因此不会触发回滚操作。

如果非要触发事务回滚,则需要在事务注解指定会触发事务回滚操作的异常类型,如果需要自定义抛出异常后反馈前端的数据,那么需要自定义异常,

自定义异常将会在下一随笔详细讲解。

经过测试总结:

(1)父级方法开启事务 @Transactional,父级发生异常,不仅父级会回滚,他调用的所有子方法都会回滚,也就是说,回滚事务父级可以影响所有子级.
(2)如果子级开了事务,父级没有开,发生异常,则仅仅让子级方法回滚,如果父级也开了事务,那么所有的子级将会和父级一起回滚。

2.操作

(1)提前配置好spring boot + mybatis

目录结构

spring boot 使用 mybatis 开启事务回滚 的总结

红色箭头的文件是必要的,

(2)导入依赖包

spring boot 使用 mybatis 开启事务回滚 的总结

完整源码

spring boot 使用 mybatis 开启事务回滚 的总结spring boot 使用 mybatis 开启事务回滚 的总结
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cen.cloud</groupId>
<artifactId>cen-mycloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>rabbitmq-producer-1004</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>rabbitmq-producer-1004</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency> <!--eureka 注册中心依赖包 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency> <!-- 消息中间件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<version>2.1.6.RELEASE</version>
</dependency> <!-- MySQL 依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<!-- <scope>runtime</scope>-->
<version>5.1.30</version>
</dependency>
<!--MySQL 数据源 依赖包-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency> <!-- mybatis依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
<!-- mybatis的逆向工程依赖包-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency> </dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

(3)启动类开启事务管理

spring boot 使用 mybatis 开启事务回滚 的总结

(4)此时的数据库表信息

spring boot 使用 mybatis 开启事务回滚 的总结

3.测试

(1)父级方法不开启事务,子级开启,让子级方法触发异常

spring boot 使用 mybatis 开启事务回滚 的总结

spring boot 使用 mybatis 开启事务回滚 的总结

启动后访问 http://localhost:1004/sw

spring boot 使用 mybatis 开启事务回滚 的总结

返回了500错误

报了个异常

spring boot 使用 mybatis 开启事务回滚 的总结

查看数据库表信息

spring boot 使用 mybatis 开启事务回滚 的总结

可见父级方法并没有回滚,子级方法事务回滚了

(2)恢复数据库表信息,

父级方法不开启事务,子级开启,让子级方法catch捕获触发异常

父级方法不变,修改子级方法

spring boot 使用 mybatis 开启事务回滚 的总结

启动后访问 http://localhost:1004/sw

spring boot 使用 mybatis 开启事务回滚 的总结

控制台打印

spring boot 使用 mybatis 开启事务回滚 的总结

查看数据库

spring boot 使用 mybatis 开启事务回滚 的总结

两次sql操作都执行了,子方法触发了异常,并没有做事务回滚操作,因为catch将服务降级了

那怎么办?

希望既可以做事务回滚操作,又能让前端获取指定的反馈信息怎么操作?

答案是手动抛出异常

throw new RuntimerException("这里写上你需要的骚话");

(3)恢复数据库表信息,

父级方法不开启事务,子级开启,让子级方法catch捕获触发异常后,手动抛出异常

父级方法不变,修改子级方法

spring boot 使用 mybatis 开启事务回滚 的总结

启动后访问 http://localhost:1004/sw

spring boot 使用 mybatis 开启事务回滚 的总结

控制台打印

spring boot 使用 mybatis 开启事务回滚 的总结

查看数据库

spring boot 使用 mybatis 开启事务回滚 的总结

可见,子级方法事务回滚了,但是父级没有,因为父级没有开启事务。

(4)如果使用 throw new Exception() 抛出异常则无法触发事务回滚

spring boot 使用 mybatis 开启事务回滚 的总结

恢复数据库后,启动工程,访问http://localhost:1004/sw

spring boot 使用 mybatis 开启事务回滚 的总结

查看数据库

spring boot 使用 mybatis 开启事务回滚 的总结

可见,不能使用throw new Exception()

(5)恢复数据库,

在事务注解指定抛出的异常则可以让检查性异常触发事务

spring boot 使用 mybatis 开启事务回滚 的总结

父级方法不变,修改子级方法

启动工程,访问http://localhost:1004/sw

spring boot 使用 mybatis 开启事务回滚 的总结

查看数据库

spring boot 使用 mybatis 开启事务回滚 的总结

显然 ,子级方法做了事务回滚操作了,父级没影响

(6)好了这里开始需要修改父级啦,

在父级添加事务注解

spring boot 使用 mybatis 开启事务回滚 的总结

子级方法不变

spring boot 使用 mybatis 开启事务回滚 的总结

启动工程,访问http://localhost:1004/sw

spring boot 使用 mybatis 开启事务回滚 的总结

查看数据库

spring boot 使用 mybatis 开启事务回滚 的总结

显然,子级抛出异常,做了事务回滚操作,父级也做了事务回滚操作

(7)恢复数据库,删除子级方法事务注解,即关闭子级事务,父即开启事务

spring boot 使用 mybatis 开启事务回滚 的总结

启动工程,访问http://localhost:1004/sw

spring boot 使用 mybatis 开启事务回滚 的总结

查看数据库

spring boot 使用 mybatis 开启事务回滚 的总结

显然,子级抛出异常,做了事务回滚操作,父级也做了事务回滚操作,即便子级没有开启事务,只有父级开启,

因此可见,只要父级开启了事务,不论是子级还是父级触发了非检查异常都会做事务回滚,如果是检查异常,则需要在事务注解指定异常类型。

(8)如果子级方法不触发异常,而是在父级触发,那么子级方法是否会回滚?

答案是会的

修改父级方法

spring boot 使用 mybatis 开启事务回滚 的总结

修改子级方法

spring boot 使用 mybatis 开启事务回滚 的总结

启动工程,访问http://localhost:1004/sw

spring boot 使用 mybatis 开启事务回滚 的总结

查看数据库

spring boot 使用 mybatis 开启事务回滚 的总结

显然,父级开启了事务且抛出异常,做了回滚操作,子级没有开启事务也没有抛出异常,仍然做了事务回滚操作