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


    1.前言  

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

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

    这就是事务操作。

      事务有四大特性

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

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

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

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

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

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

    经过测试总结:

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

    2.操作

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

    目录结构

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

    (2)导入依赖包

     完整源码

    <?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>
    View Code

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

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

    3.测试

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

     

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

     返回了500错误

    报了个异常

     查看数据库表信息

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

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

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

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

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

    控制台打印

     查看数据库

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

    那怎么办?

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

    答案是手动抛出异常

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

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

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

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

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

     控制台打印

    查看数据库

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

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

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

     查看数据库

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

    (5)恢复数据库,

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

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

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

     查看数据库

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

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

    在父级添加事务注解

     子级方法不变

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

     

     查看数据库

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

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

      

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

     查看数据库

     

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

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

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

    答案是会的

    修改父级方法

    修改子级方法

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

     查看数据库

     

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

  • 相关阅读:
    17 盒子模型
    16 input默认样式清除
    15 组合选择器
    14 CSS权重深入
    13 CSS样式权重问题
    12 子代选择器和后代选择器
    11 CSS的三种引入方式和基本选择器
    10 table标签
    NOIP1998拼数
    NOIP1998车站
  • 原文地址:https://www.cnblogs.com/c2g5201314/p/13163097.html
Copyright © 2020-2023  润新知