Spring事务传播机制--包含用例解释

article/2025/9/21 1:07:08

Spring事务传播机制

一、何为Spring传播机制:

Spring事务的传播机制就是,事务如何在方法的调用如何传播。

二、使用传播机制的时候的关键点:
  • 使用声明式的事务时,调用方法和被调用方法不能在同一个类。比如同在一个service方法中,这样是不会生效的。Spring的事务分为编程式和声明式的注解,我们一般使用声明方式的注解,利用@Transactional注解标记需要使用事务的类,Spring会利用AOP为我们在方法执行前启动事务,接受后提交和关闭事务。而AOP是基于动态代理的实现,生成代理对象,调用代理对象实现事务,而在同一个类中的调用,就会在这个类的对象调用this.method(),没有用到代理,也不会有事务。

  • 使用Spring事务的方法需要被Spring所管理。不然Spring无法通过AOP生成事务。

  • 确保Spring开启事务支持。

三、理解事务传播机制的角度(个人见解)

刚开始,学习这个Spring事务传播机制的时候,一直纠结调用方法和被调用存在事务这一概念。其实如果从被调用的角度看存在和不存在事务,就能很好的理解这些传播机制。通过下面一些测试,我先猜想结果,在验证结果,也能证实自己是否理解了Spring事务的传播。

四、Spring事务传播的七种方式

ps:测试其中方式的例子都是同一个,就是一个用户修改方法,修改用户名称;一个插入修改日志的方法,插入修改日志,在修改方法内调用插入日志的方法,目的是让两个数据库操作具有原子性,所以应用事务。同时利用除数为0创造异常,更好的测试。

一、REQUIRE
    @Override@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Throwable.class)public void updateUserName(String userName) {User user = new User();user.setId(1);user.setUserName(userName);userMapper.updateUserName(user);userChangeLogService.saveLog(user.getId());}
    @Override@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Throwable.class)public void saveLog(Integer userId) {UserChangeLog userChangeLog = new UserChangeLog();userChangeLog.setOpratorUserId(userId);userChangeLogMapper.insert(userChangeLog);int i = 10 / 0;}

两个方法都是才有默认的事务传播属性Propagation.REQUIRED

Propagation.REQUIRED:如果当前存在事务,那么就加入这个事务,不存在就新建一个事务。

结果:这里也是两个方法都没有将操作成功,因为REQUIRE的事务传播机制下,调用者存在了一个事务,被调用者在已经存在事务的情况下,加入调用者这个事务,而不自己新创建,所以两者在同一事务种,被调用方法发生异常,整个事务回滚,都不操作成功。

SUPPORTS

Propagation.SUPPORTS:如果当前有事务,加入事务,如果没有则不使用事务

    @Override@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Throwable.class)public void updateUserName(String userName) {User user = new User();user.setId(1);user.setUserName(userName);userMapper.updateUserName(user);userChangeLogService.saveLog(user.getId());}
    @Override@Transactional(propagation = Propagation.SUPPORTS,rollbackFor = Throwable.class)public void saveLog(Integer userId) {UserChangeLog userChangeLog = new UserChangeLog();userChangeLog.setOpratorUserId(userId);userChangeLogMapper.insert(userChangeLog);int i = 10 / 0;}

调用方法的传播属性是Propagation.REQUIRED,被调用的是Propagation.SUPPORTS

结果:这里也是两个方法都没有将数据操作成功–用户名称没有修改,修改日志也没有插入,发生了异常,两个数据操作都回滚了。因为调用方法存在事务,而被调用方法可以支持事务,有则加入到这个事务中,所以两方法处于同一事务,有异常则两者都回滚。

   @Override// @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Throwable.class)public void updateUserName(String userName) {User user = new User();user.setId(1);user.setUserName(userName);userMapper.updateUserName(user);userChangeLogService.saveLog(user.getId());}
    @Override@Transactional(propagation = Propagation.SUPPORTS,rollbackFor = Throwable.class)public void saveLog(Integer userId) {UserChangeLog userChangeLog = new UserChangeLog();userChangeLog.setOpratorUserId(userId);userChangeLogMapper.insert(userChangeLog);int i = 10 / 0;}

调用方法的没有事务,被调用的是Propagation.SUPPORTS

结果:这里也是两个方法都将数据操作成功–用户名称修改,修改日志也插入即使有异常,因为SUPPORTS没有处在事务中,所以被调用方法也没使用事务执行,即使有异常也没有回滚

三、NOT_SUPPORTED

NOT_SUPPORTED:表示不支持事务,如果有事务也不加入事务,没有事务以非事务运行

  @Override
//    @Transactional(rollbackFor = ArithmeticException.class)public void updateUserName(String userName) {User user = new User();user.setId(1);user.setUserName(userName);userMapper.updateUserName(user);saveLog(user.getId());}@Override@Transactional(propagation = Propagation.NOT_SUPPORTED,rollbackFor = ArithmeticException.class)public void saveLog(Integer userId) {UserChangeLog userChangeLog = new UserChangeLog();userChangeLog.setOpratorUserId(userId);userChangeLogMapper.insert(userChangeLog);int i = 10 / 0;}

调用方法没有事务,被调用的是pagation = Propagation.NOT_SUPPORTED

结果:调用方法没有事务,被调用方法不支持事务,即使报错,数据库都操作成功。

    @Override@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Throwable.class)public void updateUserName(String userName) {User user = new User();user.setId(1);user.setUserName(userName);userMapper.updateUserName(user);userChangeLogService.saveLog(user.getId());//调用方发生异常int i = 10 / 0;}
    @Override@Transactional(propagation = Propagation.NOT_SUPPORTED,rollbackFor = Throwable.class)public void saveLog(Integer userId) {UserChangeLog userChangeLog = new UserChangeLog();userChangeLog.setOpratorUserId(userId);userChangeLogMapper.insert(userChangeLog);int i = 10 / 0;}

调用方法的传播属性是Propagation.REQUIRED,被调用的是pagation = Propagation.NOT_SUPPORTED,且调用方法发生异常,被调用方法也发生异常。

结果:调用方法没有操作数据库成功,因为REQUIRED新建了一个新的事务,发生异常回滚。但是被调用方法操作数据库成功,因为NOT_SUPPOTS不支持事务,即使存在事务也不加入,所以即使有异常,也不回滚。

四、REQUIRES_NEW

REQUIRES_NEW:不管是否存在事务,都以最新的事务执行,执行完在执行旧的事务

    @Override@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Throwable.class)public void updateUserName(String userName) {User user = new User();user.setId(1);user.setUserName(userName);userMapper.updateUserName(user);userChangeLogService.saveLog(user.getId());int i = 10 / 0;}
    @Override@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Throwable.class)public void saveLog(Integer userId) {UserChangeLog userChangeLog = new UserChangeLog();userChangeLog.setOpratorUserId(userId);userChangeLogMapper.insert(userChangeLog);}
}

调用方法的传播属性是Propagation.REQUIRED,被调用方法的是Propagation.REQUIRES_NEW

结果:调用方法操作数据库失败,因为自己所在得事务中有异常,且有事务,操作回滚。被调用操作数据库成功,因为创建了一个新的事务,与已经存在的事务无关,没有异常正常执行,调用方法和被调用方法处于两个不同得事务,因为.REQUIRES_NEW以新的事务执行。

五、MANDATORY

MANDATORY(强制的):必须在一个事务中执行,如果没有事务,则抛出异常

     @Override//@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Throwable.class)public void updateUserName(String userName) {User user = new User();user.setId(1);user.setUserName(userName);userMapper.updateUserName(user);userChangeLogService.saveLog(user.getId());}
    @Override@Transactional(propagation = Propagation.MANDATORY,rollbackFor = Throwable.class)public void saveLog(Integer userId) {UserChangeLog userChangeLog = new UserChangeLog();userChangeLog.setOpratorUserId(userId);userChangeLogMapper.insert(userChangeLog);//int i = 10 / 0;}

调用方法没有加入事务,被调用方法使用MANDATORY

结果:调用方法正常执行数据库操作,被调用方法抛出异常,且没有执行数据库操作(异常中断了程序),抛出的异常时因为被调用法必须在事务中执行,没有事务,抛出异常,异常如下:
在这里插入图片描述

六、NEVER

NEVER:以非事务的方式执行,如果存在事务异常

    @Override@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Throwable.class)public void updateUserName(String userName) {User user = new User();user.setId(1);user.setUserName(userName);userMapper.updateUserName(user);userChangeLogService.saveLog(user.getId());}
    @Override@Transactional(propagation = Propagation.NEVER,rollbackFor = Throwable.class)public void saveLog(Integer userId) {UserChangeLog userChangeLog = new UserChangeLog();userChangeLog.setOpratorUserId(userId);userChangeLogMapper.insert(userChangeLog);//int i = 10 / 0;}

调用方法使用的QEQUIRE,会创建一个新的事务,被调用方法使用NEVER,两个方法都没有额外的异常。

结果:调用方法操作数据库不成功,被调用方法操作数据库不成功。因为被调用方法时NEVER的传播机制,调用方法有事务,被调用方法会抛出异常,导致本身执行不成功,抛出的异常也会导致调用方法的事务回滚,操作不成功。抛出的异常如下:
在这里插入图片描述

七、PROPAGATION_NESTED

PROPAGATION_NESTED:如果调用者不存在事务,那么被调用者自己创建事务,这种情况和REQUIRE一样。如果调用者存在事务,那么被调用者就在调用者的事务里嵌套一个事务,称为嵌套事务。

使用嵌套事务是用条件的:

  • 数据库的支持

  • JDK 1.4 才支持 java.sql.Savepoint 。所以JDK必须在1.4 及以上

  • 还需要Spring中配置nestedTransactionAllowed=true。


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

相关文章

spring事务传播机制实例讲解

对于SQL事务的概念以及ACID性质,可以参见我的另一篇博文 http://kingj.iteye.com/admin/blogs/1675011spring的管理的事务可以分为如下2类: 逻辑事务 在spring中定义的事务通常指逻辑事务,提供比物理事务更抽象,方便的事务配置管…

Spring事务及事务传播机制

一.事务的含义:多个操作封装在一起,要么同时执行成功,一旦有一个操作执行失败,那么全部执行失败。这里给大家举个例子:比如A给B转账50元,而B没有收到这50元,此时A转账B这个操作也需要进行回滚,恢复到A给B没…

【 Spring 事务传播机制 】

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

Spring事务与事务传播机制

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

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

Spring事务、事务隔离级别、事务传播机制 一、为什么需要事务?(回顾)二、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的事务传播机制:是指规定当程序中出现了多个方法出现了嵌套调用的时候,事务是如何进行传递的 支持当前事务:要有房子的 不支持当前事务:不许要有房子的 嵌套事务 1)定义:咱们之前所说的事务,都是针对一个方法的,咱们的Spring事务传播机…

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

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

Spring中的事务传播机制

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

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

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

事务传播行为

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

[事务] 事务的传播机制

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

事物的传播机制

目录 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 事务传播机制:就是事务在多个方法的调用中是如何…

Spring事务传播机制

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

Spring事务传播的7种机制

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

事务的传播机制

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

Spring事务传播机制详解

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

反射原理详谈

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

Java反射的作用与原理

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