【 Spring 事务传播机制 】

article/2025/9/21 1:16:44

文章目录

  • 一、概念
  • 二、为什么需要事务传播机制?
  • 三、事务传播机制有哪些?
  • 四、Spring 事务传播机制使⽤和各种场景演示
    • 4.1 ⽀持当前事务(REQUIRED)
    • 4.2 不⽀持当前事务(REQUIRES_NEW)
    • 4.3 NESTED 嵌套事务
    • 4.4 嵌套事务和加⼊事务的区别

一、概念

Spring 事务传播机制是指多个包含事务的⽅法相互调⽤时,事务是如何在这些⽅法间进⾏传递的

二、为什么需要事务传播机制?

事务隔离级别是保证多个并发事务执⾏的可控性(稳定性的),⽽事务传播机制是保证⼀个事务在多个调⽤⽅法间传递的可控性

事务隔离级别解决的是多个事务同时调⽤⼀个数据库的问题,如下图所示:
在这里插入图片描述

⽽事务传播机制解决的是⼀个事务在多个节点(⽅法)中传递的问题,如下图所示:
在这里插入图片描述

三、事务传播机制有哪些?

Spring 事务传播机制包含以下 7 种:

  1. Propagation.REQUIRED:默认的事务传播级别,它表示如果当前存在事务,则加⼊该事务;如果当前没有事务,则创建⼀个新的事务。
  2. Propagation.SUPPORTS:如果当前存在事务,则加⼊该事务;如果当前没有事务,则以⾮事务的⽅式继续运⾏。
  3. Propagation.MANDATORY:(mandatory:强制性)如果当前存在事务,则加⼊该事务;如果当前没有事务,则抛出异常。
  4. Propagation.REQUIRES_NEW:表示创建⼀个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部⽅法是否开启事务,Propagation.REQUIRES_NEW 修饰的内部⽅法会新开启⾃⼰的事务,且开启的事务相互独⽴,互不⼲扰。
  5. Propagation.NOT_SUPPORTED:以⾮事务⽅式运⾏,如果当前存在事务,则把当前事务挂起。
  6. Propagation.NEVER:以⾮事务⽅式运⾏,如果当前存在事务,则抛出异常。
  7. Propagation.NESTED:如果当前存在事务,则创建⼀个事务作为当前事务的嵌套事务来运⾏;如果当前没有事务,则该取值等价于 PROPAGATION_REQUIRED。

以上 7 种传播⾏为,可以根据是否⽀持当前事务分为以下 3 类:
在这里插入图片描述

如何理解当前事务?举个例子:

方法A(包含事务a) 去调用 方法B(包含事务b) ,此时A就是外部方法,而a就是外部方法事务即所谓的当前事务,而B就是内部方法,b就是内部方法事务。所以所谓的当前事务,就是外部方法的事务

上面说的很抽象,我们通过具体的代码来说明,如下

四、Spring 事务传播机制使⽤和各种场景演示

目标实现:当在用户表中添加一条数据后,相应的日志表也会记录一条消息

正确的业务代码是当我添加用户成功时就会自动添加一条日志,所以直接在一个service里调用这两个添加接口就行了。而下面我们为了验证事务的传播机制特意将用户添加和日志添加方法分开,分别在 controller 中调用 !!

准备工作:

  1. 创建用户表和日志表
    在这里插入图片描述

  2. 准备相应的实体类
    在这里插入图片描述

  3. mapper 代码实现
    在这里插入图片描述

  4. xml 文件实现

<insert id="add">insert into loginfo(name,description)values (#{name}, #{description})
</insert>
<insert id="add">insert into userinfo(username,password) values (#{username},#{password})
</insert>
  1. controller 代码实现
@RestController
public class UserController {@Resourceprivate UserService userService;@Resourceprivate LogService logService;@Transactional(propagation = Propagation.REQUIRED) //默认就是 REQUIRED@RequestMapping("/add3")public int add3(UserInfo userInfo) {if (userInfo == null ||!StringUtils.hasLength(userInfo.getUsername()) ||!StringUtils.hasLength(userInfo.getPassword())) {return 0;}int userResult = userService.add(userInfo);System.out.println("添加用户:" + userResult);LogInfo logInfo = new LogInfo();logInfo.setName("添加用户的姓名");logInfo.setDescription("添加用户结果:" + userResult);int logResult = logService.add(logInfo);return userResult;}
}

具体 service 代码实现,以及验证结果

4.1 ⽀持当前事务(REQUIRED)

以下代码实现中,先开启事务先成功插⼊⼀条⽤户数据,然后再执⾏⽇志报错,⽽在⽇志报错是发⽣了异常,观察 propagation = Propagation.REQUIRED 的执⾏结果

UserService 实现代码如下:

@Service
public class UserService {@Resourceprivate UserInfoMapper userInfoMapper;@Transactional(propagation = Propagation.REQUIRED)public int add(UserInfo userInfo){return userInfoMapper.add(userInfo);}
}

LogService 实现代码如下:

@Service
public class LogService {@Resourceprivate LogInfoMapper logInfoMapper;@Transactional(propagation = Propagation.REQUIRED)public int add(LogInfo logInfo) {int result = logInfoMapper.add(logInfo);System.out.println("添加日志结果:" + result);int number = 10 / 0;return result;}
}

验证前的数据表:
在这里插入图片描述

通过 url 访问,控制台结果:
在这里插入图片描述

再次查看数据表:
在这里插入图片描述

我们发现,两张数据表都没有成功插入数据,没有存在异常的添加用户操作也同样失败了。这是为什么呢?

这是因为我们将两个添加方法上的事务都设置成了 REQUIRED ,而在前面我们知道了它表示如果当前存在事务,则加⼊该事务;如果当前没有事务,则创建⼀个新的事务。而 controller 中的添加方法我们设置了事务的,该添加方法调用了用户添加和日志添加方法,所以他们两的事务直接加入到了外部方法事务中,成为了一个整体!现在他们处于同一事务中,当添加日志操作出现异常后进行回滚操作,整个事务都会实现回滚操作,所以用户添加操作也会回滚,用户添加操作失败


4.2 不⽀持当前事务(REQUIRES_NEW)

UserController 类中的代码不变,将添加⽤户和添加⽇志的⽅法修改为 REQUIRES_NEW 不⽀持当前事务,重新创建事务,观察执⾏结果

重复代码就不写了,只需要将两个添加方法中的事务的传播机制设置为 REQUIRES_NEW

通过 url 访问,控制台结果:
在这里插入图片描述

查看数据表结果
在这里插入图片描述

我们发现,用户表中成功插入了数据,而日志表中还是为空!!

分析如下,我们将两个添加方法的事务传播机制设置为了 REQUIRES_NEW,它表示创建⼀个新的事务,如果当前存在事务,则把当前事务挂起。即外部方法事务是否存在已经不重要了,两个添加方法都创建了各自的事务,且互不干扰。所以添加日志操作出现异常,它的事务就会进行回滚操作,而该回滚操作并不会影响处于另一个事务的添加用户操作 ! 所以用户添加能够成功,而日志添加失败


4.3 NESTED 嵌套事务

老样子,重复代码就不写了,只需要将两个添加方法中的事务的传播机制设置为 NESTED
并使用 try…catch 将添加日志中的异常捕获(使用 NESTED 的前提) 如下:

logservice 代码修改

@Service
public class LogService {@Resourceprivate LogInfoMapper logInfoMapper;@Transactional(propagation = Propagation.NESTED)public int add(LogInfo logInfo) {int result = logInfoMapper.add(logInfo);System.out.println("添加日志结果:" + result);try {int number = 10 / 0;} catch (Exception e) {TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}return result;}
}

通过 url 访问,控制台结果:
在这里插入图片描述

查看数据表结果:
在这里插入图片描述

用户添加操作成功,而日志添加操作失败 !!由此可见,日志添加事务已经回滚,但是该嵌套事务不会回滚嵌套之前的事务即外部方法事务,也就是说嵌套事务可以实现部分事务回滚!!

那嵌套事务是如何实现部分事务回滚的呢?嵌套事务只所以能够实现部分事务的回滚,是因为事务中有⼀个保存点(savepoint)嵌套事务进⼊之后相当于新建了⼀个保存点,⽽滚回时只回滚到当前保存点,因此之前的事务是不受影响的。⽽ REQUIRED 是加⼊到当前事务中,并没有创建事务的保存点,因此出现了回滚就是整个事务回滚,这就是嵌套事务和加⼊事务的区别

(重要) 前面我们说使用 try…catch 将添加日志中的异常捕获是使用 NESTED 的前提,如果不这样做的话日志添加中的回滚操作会持续往上找调⽤它的⽅法和事务进行回滚,最终我们的外部方法事务也会被回滚,所以即使用户添加操作没有异常出现,该操作也会被回滚,最终的结果是⽤户表和⽇志表都没有添加任何数据 !!

与嵌套事务相关文档 !!!


4.4 嵌套事务和加⼊事务的区别

前面我们分别演示了这两种事务,也对各自的结果进行了分析

REQUIRED 是如果当前存在事务就加入该事务,成为该事务的一部分,既然都是一家人了,大家有难一起担!所以当其中的一个事务出现异常进行了回滚操作,那么整个事务都将会进行回滚操作。而 NESTED 是如果当前存在事务,则创建⼀个事务作为当前事务的嵌套事务来运⾏,即附属在当前事务,并没有真正的成为一家人,所以当这个附属事务进行回滚操作时,当前事务并不会进行回滚,也就是说嵌套事务可以实现部分事务回滚 !!

总结如下:

  1. 整个事务如果全部执⾏成功,⼆者的结果是⼀样的。
  2. 如果事务执⾏到⼀半失败了,那么加⼊事务整个事务会全部回滚;⽽嵌套事务会局部回滚,不会影响上⼀个⽅法中执⾏的结果

http://chatgpt.dhexx.cn/article/AY5coQb3.shtml

相关文章

Spring事务与事务传播机制

目录 1.事务的基本概念 2.Spring事务的实现 3.事务隔离级别 4.事务传播机制 1.事务的基本概念 关于事务的一些基础概念我已经在MYSQL中讲解过了&#xff0c;有不了解的可以移步至此篇文章&#xff1a;MySQL基础——数据库索引与事务_invictusQAQ的博客-CSDN博客 2.Spring…

Spring事务、事务隔离级别、事务传播机制

Spring事务、事务隔离级别、事务传播机制 一、为什么需要事务&#xff1f;(回顾)二、Spring中事务的实现2.1 MySQL中的事务使用 (回顾)2.2 Spring编程式事务2.3 Spring 声明式事务2.3.1 Transactional 使用2.3.2 Transactional 作用范围2.3.3 Transactional 参数说明2.3.4 注意…

Spring 事务和事务的传播机制

1.Spring 中事务的实现方式 Spring 中的操作主要分为两类: 编程式事务 (了解) 声明式事务 编程式事务就是手写代码操作事务, 而声明式事务是利用注解来自动开启和提交事务. 并且编程式事务用几乎不怎么用. 这就好比汽车的手动挡和自动挡, 如果有足够的的钱, 大部分人应该都会选…

【Spring Boot】事务和事务传播机制

文章目录 1. 事务简单介绍2. Spring 中事务的实现2.1 Spring 手动操作事务2.2 Spring 声明式事务 3. Transactional 注解介绍3.1 Transactional 作用范围3.2 Transactional 参数说明3.3 Transactional 出现异常注意事项3.4 Transactional 工作原理 4. 事务隔离级别4.1 事务特性…

SpringBoot事务传播机制

Spring的事务传播机制:是指规定当程序中出现了多个方法出现了嵌套调用的时候&#xff0c;事务是如何进行传递的 支持当前事务:要有房子的 不支持当前事务:不许要有房子的 嵌套事务 1)定义:咱们之前所说的事务&#xff0c;都是针对一个方法的&#xff0c;咱们的Spring事务传播机…

Spring的事务传播机制(通俗易懂)

概述 Spring的事务传播机制有7种&#xff0c;在枚举Propagation中有定义。 1.REQUIRED PROPAGATION_REQUIRED&#xff1a;如果当前没有事务&#xff0c;就创建一个新事务&#xff0c;如果当前存在事务&#xff0c;就加入该事务&#xff0c;该设置是最常用的默认设置。 Tra…

Spring中的事务传播机制

目录 前言 1、Spring&#xff08;Spring Boot&#xff09;实现事务 1.1、通过代码的方式手动实现事务 1.2、通过注解Transactional的方式实现声明式事务 1.2.1、实现: 1.2.2、程序中有try-catch时&#xff0c;程序发生异常事务不会回滚 解决方案一&#xff1a;将异常抛出去 …

事务的7种传播机制和演示

文章目录 一、事务的传播机制1.1、nested 事务的几点说明&#xff1a; 二、示例2.1、前言&#xff1a;2.2、准备测试方法1&#xff09;创建beans.xml&#xff0c;开启事务2&#xff09;创建实体类和表&#xff08;表创建读者可自定义创建&#xff09;3&#xff09;创建service接…

事务传播行为

原文作者&#xff1a;https://blog.csdn.net/soonfly/article/details/70305683 事务传播行为 什么叫事务传播行为&#xff1f;听起来挺高端的&#xff0c;其实很简单。 即然是传播&#xff0c;那么至少有两个东西&#xff0c;才可以发生传播。单体不存在传播这个行为。 事务传…

[事务] 事务的传播机制

前言&#xff1a; Spring的事务&#xff0c;也就是数据库的事务操作&#xff0c;符合ACID标准&#xff0c;也具有标准的事务隔离级别。 但是Spring事务有自己的特点&#xff0c;也就是事务传播机制。 所谓事务传播机制&#xff0c;也就是在事务在多个方法的调用中是如何传递的&…

事物的传播机制

目录 1、事务的传播机制 2、测试 2.1、准备测试方法 2.2、事务传播机制的测试 2.2.1、REQUIRED 2.2.2、NOT_SUPPORTED 2.2.3、REQUIRES_NEW 2.2.4、MANDATORY 2.2.5、NEVER 2.2.6、SUPPORTS 2.2.7、NESTED 事务传播机制&#xff1a;就是事务在多个方法的调用中是如何…

Spring事务传播机制

目录 一、事务在Spring中是如何运作的 1.1 开启事务(DataSourceTransactionManager.doBegin) 二、Spring的事务传播机制 2.1 子事务的传播机制为REQUIRED 2.2 子事务的传播机制为REQUIRES_NEW 2.3 子事务的传播机制为NESTED 当我们在使用Spring所提供的事务功能时&#x…

Spring事务传播的7种机制

Spring 事务传播机制包含以下 7 种&#xff1a; 1. Propagation.REQUIRED&#xff1a;默认的事务传播级别&#xff0c;它表示如果当前存在事务&#xff0c;则加入该事务&#xff1b;如果 当前没有事务&#xff0c;则创建一个新的事务。 2. Propagation.SUPPORTS&#xff1a;如果…

事务的传播机制

目录 1.形象说明&#xff1a; 2.代码演示&#xff1a; 2.1 REQUIRED 2.1.1 验证共用一个事务 2.1.2 验证当前没有事务&#xff0c;就新建一个事务 2.2 SUPPORTS 2.2.1 支持使用当前事务 2.2.2 如果当前事务不存在&#xff0c;则不使用事务 2.3 MANDATORY 2.3.1 支持…

Spring事务传播机制详解

前言&#xff1a; Spring的事务&#xff0c;也就是数据库的事务操作&#xff0c;符合ACID标准&#xff0c;也具有标准的事务隔离级别。 但是Spring事务有自己的特点&#xff0c;也就是事务传播机制。 所谓事务传播机制&#xff0c;也就是在事务在多个方法的调用中是如何传递的&…

反射原理详谈

什么是反射&#xff1f; 反射是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法&#xff1b;对于任意一个对象&#xff0c;都能够调用它的任意一个方法和属性&#xff1b;这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言…

Java反射的作用与原理

Java反射的作用与原理 定义 反射机制是指在程序的运行状态中&#xff0c;可以构造任意一个类的对象&#xff0c;可以了解任意一个对象所属的类&#xff0c;可以了解任意一个类的成员变量和方法&#xff0c;可以调用任意一个对象的属性和方法。在Java中&#xff0c;只要给定类…

彻底搞懂java反射技术及其原理

概述:反射是java中最强大的技术之一,很多高级框架都用到了反射技术,面试中也是经常问的点,所以搞懂反射非常重要&#xff01; 文章目录 1.反射是什么?2.反射的底层原理3.三种方式获取Class对象4.反射的优缺点5.反射的应用场景6.反射的常用API 1.反射是什么? java反射机制指…

java反射原理-重要

一&#xff0c;反射是什么&#xff08;反射是框架设计的灵魂&#xff09; 1&#xff0c;JAVA反射机制是在运行状态中 对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法&#xff1b; 对于任意一个对象&#xff0c;都能够调用它的任意一个方法和属性&#xff1b; …

java 反射机制原理 简述

什么是反射机制&#xff1f; 1、在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的属性和方法。 2、对于任意一个对象&#xff0c;都能够调用它的任何方法和属性。这种动态获取信息以及动态调用对象的方法的功能称为JAVA的反射。 反射的作用 1、在运行…