首页> 文章> 详情

Spring Boot 事物回滚实验

教程分享 > Java教程 (5405) 2024-04-17 12:31:28

1.开启事物

通过注解开启
@EnableTransactionManagement 

提示: Spring Boot  以Spring 5.0为基础的版本无需注解自动开启事物

2.测试事物

首先查询数据库中的表
默认表
默认表中有一条数据;

2.1默认不用事物

首先是不开启,创建两个数据代码如下:
public void test() {
        SystemMenu m1=new SystemMenu();
        m1.setName("test2");
        m1.setTerminal("00");
        menuExtMapper.insertSelective(m1);
        SystemMenu m2=new SystemMenu();
        m2.setId(1);//重复ID 数据库会报错
        m2.setName("test3");
        m2.setTerminal("00");
    }

执行上面的代码:
执行错误
通过控制台我们可以看到已经输出了 主键冲突的异常,我们再看看数据库:
执行结果数据库查询
通过数据库查询可以看到,test2数据已经存入数据库,test3肯定就是失败了,同时证明了默认没开启事物,遇到错误并不会回滚。

2.2通过注解@Transactional开启事物

首先我们将数据库还原,删除掉test2数据,如下:
操作示例图-bfcdc45b17cc42dc948eb176da651f93.png
程序代码如下:
@Transactional
    public void test() {
        SystemMenu m1=new SystemMenu();
        m1.setName("test2");
        m1.setTerminal("00");
        menuExtMapper.insertSelective(m1);
        SystemMenu m2=new SystemMenu();
        m2.setId(1);//重复ID 数据库会报错
        m2.setName("test3");
        m2.setTerminal("00");
        menuExtMapper.insertSelective(m2);
    }
执行上方代码:
同样的执行错误

从控制台看,同样输出了主键冲突的错误,我们再看看数据库中的数据:
数据库数据

从数据可以看到,并没有数据存入。这里也就证明了事物开启成功,遇到错误就会同一回滚保证了数据的一致性。

提示:默认情况下,@Transactional注解只对RuntimeException及其子类异常有效。

证明上方的观点,下面以代码示例:
@Transactional
    public void test() throws Exception {
        SystemMenu m1=new SystemMenu();
        m1.setName("test2");
        m1.setTerminal("00");
        menuExtMapper.insertSelective(m1);

        if (1==1){
            throw new Exception("EEEEEE");
        }
        SystemMenu m2=new SystemMenu();
        m2.setId(1);//重复ID 数据库会报错
        m2.setName("test3");
        m2.setTerminal("00");
        menuExtMapper.insertSelective(m2);
    }
上方代码,在处理数据中间主动抛出了Exception异常,执行代码观察控制台以及数据库:
控制台
控制台
 
数据库
数据库

通过上方我们可以看到,抛出Exception的情况下事物并没有生效,test2已经存入数据库中。

提示:
可以通过注解@Transactional中的rollbackFor 来指定事物遇到那些异常会启用,同样也可以通过noRollbackFor指定那些异常不会滚
例如下方的配置事物遇到所有的Exception都会回滚
@Transactional(rollbackFor = {Exception.class})

2.3 启用事物的方法内部调用其他方法出现异常会回滚吗

首先我们蒋数据库恢复如下:
恢复数据
编写测试代码如下:
@Transactional(rollbackFor = {Exception.class})
    public void test() throws Exception {
        SystemMenu m1=new SystemMenu();
        m1.setName("test2");
        m1.setTerminal("00");
        menuExtMapper.insertSelective(m1);
        oo();
    }

    public void oo(){
        SystemMenu m2=new SystemMenu();
        m2.setId(1);
        m2.setName("test2");
        m2.setTerminal("00");
        menuExtMapper.insertSelective(m2);
    }
执行代码,观察控制台和数据库:
控制台
控制台
数据库
数据库
通过上方实验,我们可以看到事物生效了。所以内部调用其他方法出现异常同样会触发事物

提示:
调用的方法需没有标注注解@Transactional,如果标注注解会有几种情况,后方说明。

2.4 启用事物的方法内部调用其他启用事物的方法

编写测试代码1:
    @Transactional(rollbackFor = {Exception.class})
    public void test() throws Exception {
        oo();

        SystemMenu m1=new SystemMenu();
        m1.setId(1);
        m1.setName("test2");
        m1.setTerminal("00");
        menuExtMapper.insertSelective(m1);

    }

    @Transactional
    public void oo(){
        SystemMenu m2=new SystemMenu();
        m2.setName("test3");
        m2.setTerminal("00");
        menuExtMapper.insertSelective(m2);
    }
执行测试代码并观察控制台和数据库:
控制台
控制台
 
数据库
数据库

通过上方实验,我们可以知道默认情况下,@Transactional注解的方法调用@Transactional注解的方法也是可以事物统一回滚的。

注意:

  • 调用的方法上指定的Exception范围必须包含被调用方抛出异常的范围,否则可能出现不一致
  • 上方还涉及到一个知识点,事物的传播级别,默认情况下事物的传播级别为"REQUIRED",即:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。
所以上方两个方法的事物会被整合成一个事物处理。@Transactional注解也可以通过propagation 来指定传播级别,如下:
@Transactional(propagation = Propagation.REQUIRED)
事物传播的几个级别分别为:
  • REQUIRED(@Transactional注解默认值): 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。
  • SUPPORTS:前方法不需要事务上下文,但是如果存在当前事务的话,那么这个方法会在这个事务中运行。
  • MANDATORY:该方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常。不会主动开启一个事务。
  • REQUIRES_NEW:前方法必须运行在它自己的事务中。一个新的事务将被启动,如果存在当前事务,在该方法执行期间,当前事务会被挂起(如果一个事务已经存在,则先将这个存在的事务挂起)。如果使用JTATransactionManager的话,则需要访问TransactionManager。
  • NOT_SUPPORTED:该方法不应该运行在事务中,如果存在当前事务,在该方法运行期间,当前事务将被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager。
  • NEVER:表示当前方法不应该运行在事务上下文中,如果当前正有一个事务在运行,则会抛出异常。
  • NESTED:如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。如果当前事务不存在,那么其行为与REQUIRED一样。嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。


(未完待续)后续继续更新实验....

 
https://www.leftso.com/article/747.html

相关文章
1.开启事物通过注解开启@EnableTransactionManagement 提示: Spring Boot  以Spring 5.0为基础的版本无需注解自动开启事物2.测试事物首先查询数据...
引言    通过之前spring boot mybatis 整合的讲解: spring boot mybaties整合  (spring boot mybaties 整合 基于Java注解方式写...
简述本文主要通过一个简单的例子模拟实现秒杀情景,其中主要使用Redis事物进行实现spring boot为提供方便的环境
spring boot框架整合MyBatis数据库暂时选用MySQL
事务有四个特性:ACID原子性(Atomicity):事务是一个原子操作,由一系列动作组成
Spring Boot 2.0,Spring框架的Spring Boot 中的Spring Boot Actuator变化讲解。并且了解如何在Spring Boot 2.0中使用Actuator...
Spring Boot 2.0 绑定properties属性资源文件 Spring Boot 2.0 读取properties配置文件值 Spring Boot 2.0获取properties配...
spring boot入门,spring boot是一个崭新的spring框架分支项目,本文讲解其属性配置相关
spring boot 1.5整合redis实现spring的缓存框架,spring boot,redis
spring boot是一个崭新的spring框架分支项目,本文讲解基本的数据库配置
Spring Boot validation整合hibernate validator实现数据验证,Spring Boot validation使用说明,Spring Boot validat...
spring boot mybatis 整合使用讲解介绍,spring boot与MyBatis的使用讲解介绍。spring boot mybatis xml mapper方式的入门和通过一个简...
spring boot又一个spring框架的经典项目,本文讲解spring boot入门的环境配置以及第一个项目,Spring Boot 入门教程
Spring Boot 2.0 Redis整合,通过spring boot 2.0整合Redis作为spring缓存框架的实现。
spring boot 导入本地jar包spring boot maven 打war包时候导入本地jar包