一文详解Spring事务传播机制

news2025/2/21 19:34:42

背景

我们在使用Spring管理数据库事务的时候很方便,只需要在代理对象中引入注解@Transactional 就可以开启事务了。在使用@Transactional,一般主要关心两个方面,一个是异常回滚的定义(设置rollbackFor),另一个是事务传播行为的定义(设置propagation)。
默认情况,在发生 RuntimeExceptionError时会回滚,必要时可设置rollbackFor = Exception.class来回滚非运行时异常。默认的事务传播行为是支持当前的事务,如果不存在事务,则创建个新的事务。以上的默认行为可以覆盖较大一部分的应用场景, 使用起来非常方便,不用配置参数就可以适应较大一部分的应用场景。但是涉及到2个以上的服务使用事务的时候,还需要了解更多的事务传播行为

Spring事务

事务是指在数据库中执行的一系列相关操作。它们必须作为单个操作单元执行,以确保数据的一致性和完整性。在Java应用程序中,事务可以使用 JDBC 或 Java Persistence API(JPA)进行管理。

Spring 框架支持声明式和编程式事务管理

  • 编程式事务:在代码中手动的使用注释或XML配置管理事务的提交、回滚等操作,代码侵入性比较强。
  • 声明式事务(常用):基于AOP面向切面的,它将具体业务与事务处理部分解耦,代码侵入性很低。有两种实现方式:
    • 基于TXAOP的xml配置文件方式
    • 基于@Transactional注解

无论选择哪种方式, Spring 框架都提供了一致性的API来管理事务。

事务管理

事务管理器主要有三个接口:

  • PlatformTransactionManager: 提供了管理事务的基本操作,如开始事务,提交事务和回滚事务。
  • TransactionDefinition: 提供了事务的定义,如隔离级别,超时和传播行为。
  • TransactionStatus: 提供了事务的状态,如是否已提交或已回滚。

Spring 框架提供了许多实现 PlatformTransactionManager 接口的类, 其中包括:

  • DataSourceTransactionManager: 用于在JDBC事务中使用。
  • JpaTransactionManager: 用于在JPA事务中使用。
  • HibernateTransactionManager: 用于在Hibernate事务中使用。

可以根据的需要选择使用哪个事务管理器。

@Transactional注解

使用场景

  • 作用于类:当把@Transactional 注解放在类上时,表示所有该类的public方法都配置相同的事务属性信息。
  • 作用于方法:当类配置了@Transactional,方法也配置了@Transactional,方法的事务会覆盖类的事务配置信息。
  • 作用于接口:不推荐这种使用方法,因为一旦标注在Interface上并且配置了Spring AOP 使用CGLib动态代理,将会导致@Transactional注解失效

失效场景

  • 注解@Transactional配置的方法非public权限修饰;
  • 注解@Transactional所在类非Spring容器管理的bean;
  • 注解@Transactional所在类中,注解修饰的方法被类内部方法调用;
  • 业务代码抛出异常类型非RuntimeException,事务失效;
  • 业务代码中存在异常时,使用try…catch…语句块捕获,而catch语句块没有throw new RuntimeExecption异常;(最难被排查到问题且容易忽略)
  • 注解@TransactionalPropagation属性值设置错误即Propagation.NOT_SUPPORTED(一般不会设置此种传播机制)
  • mysql关系型数据库,且存储引擎是MyISAM而非InnoDB,则事务会不起作用(基本开发中不会遇到);下面基于以上场景,溪源给小伙伴们详细解释; 注意:Spring事务只有在程序发生RunTimeExceptionError时才会回滚。

原理

 

事务传播机制

Spring 事务传播机制的诞生是为了规定多个事务在传播过程中的行为的。比如方法 A 开启了事务,而在执行过程中又调用了开启事务的 B 方法,那么 B 方法的事务是应该加入到 A 事务当中呢?还是两个事务相互执行互不影响,又或者是将 B 事务嵌套到 A 事务中执行呢?所以这个时候就需要一个机制来规定和约束这两个事务的行为,这就是 Spring 事务传播机制所解决的问题

Spring 事务传播机制可使用 @Transactional(propagation=Propagation.XXX) 来定义

  • PROPAGATION_REQUIRED: 如果当前存在事务,则加入该事务;否则,创建一个新事务。

  • PROPAGATION_SUPPORTS: 如果当前存在事务,则加入该事务;否则,不使用事务。

  • PROPAGATION_MANDATORY: 如果当前存在事务,则加入该事务;否则,抛出异常。

  • PROPAGATION_REQUIRES_NEW: 创建一个新事务,并挂起当前事务(如果存在)。

  • PROPAGATION_NOT_SUPPORTED: 不使用事务;如果当前存在事务,则挂起该事务。

  • PROPAGATION_NEVER: 不使用事务;如果当前存在事务,则抛出异常。

  • PROPAGATION_NESTED: 如果当前存在事务,则在嵌套事务中执行;否则,创建一个新事务。

处理嵌套事务流程

主事务开启→主事务执行→子事务开启→子事务执行→子事务提交或 回滚→主事务提交或回滚

主事务为REQUIRED子事务为REQUIRED

 主事务为REQUIRED子事务为REQUIRES_NEW

 主事务为REQUIRED子事务为NESTED

实现方式

事务传播机制是通过 TransactionInterceptor 拦截器来实现的。TransactionInterceptor 是一个AOP拦截器,它拦截方法调用,并在方法调用之前和之后启动和提交事务。

当使用 Spring 框架进行事务管理时,需要将 TransactionInterceptor 添加到的应用程序上下文中。然后,可以使用 @Transactional 注释或使用XML配置来定义事务传播行为。

当使用 @Transactional 注释时, Spring 框架会将 TransactionInterceptor 添加到的方法上。当调用该方法时,TransactionInterceptor 会拦截该调用,并根据在注释中指定的事务传播行为来启动事务。

源码解析

在 Spring 框架中,事务管理器的实现主要包括以下几个类:

  • AbstractPlatformTransactionManager: 它是PlatformTransactionManager接口的抽象实现。它定义了事务的基本操作,如开始事务,提交事务和回滚事务。

  • DataSourceTransactionManager: 它是AbstractPlatformTransactionManager的子类,它用于在JDBC事务中使用。

  • JpaTransactionManager: 它是AbstractPlatformTransactionManager的子类,它用于在JPA事务中使用。

  • HibernateTransactionManager: 它是AbstractPlatformTransactionManager的子类,它用于在Hibernate事务中使用。

事务传播机制的实现主要包括以下几个类:

  • AbstractFallbackTransactionAttributeSource: 它是TransactionAttributeSource接口的抽象实现。它定义了如何获取事务属性。

  • AnnotationTransactionAttributeSource: 它是AbstractFallbackTransactionAttributeSource的子类,它用于从注释中获取事务属性。

  • TransactionInterceptor: 它是一个AOP拦截器,它拦截方法调用,并在方法调用之前和之后启动和提交事务。

事务传播机制的实现主要是通过 TransactionInterceptor 拦截器来实现的。TransactionInterceptor的源代码:

public class TransactionInterceptor implements MethodInterceptor {

    private PlatformTransactionManager transactionManager;

    private TransactionAttributeSource transactionAttributeSource;

    // ...

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        TransactionAttributeSource tas = getTransactionAttributeSource();
        if (tas == null) {
            // no transaction attribute source -> no transaction
            return invocation.proceed();
        }

        Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
        TransactionAttribute txAttr = tas.getTransactionAttribute(invocation.getMethod(), targetClass);
        PlatformTransactionManager tm = determineTransactionManager(txAttr);
        TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, invocation.getMethodIdentification());
        Object retVal = null;
        try {
            retVal = invocation.proceed();
        }
        catch (Throwable ex) {
            // transactional code threw exception -> rollback
            completeTransactionAfterThrowing(txInfo, ex);
            throw ex;
        }
        finally {
            cleanupTransactionInfo(txInfo);
        }
        commitTransactionAfterReturning(txInfo);
        return retVal;
    }

    // ...

}

复制代码

在这个代码中,invoke() 方法拦截了方法调用,并根据其事务属性来启动事务。

如果事务属性为PROPAGATION_REQUIRED,则创建一个新事务或加入当前事务。

如果事务属性为PROPAGATION_REQUIRES_NEW,则创建一个新事务并挂起当前事务。

如果事务属性为PROPAGATION_SUPPORTS,则将不使用事务。

如果事务属性为PROPAGATION_MANDATORY,则将抛出异常。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/438446.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python统计学:如何理解单样本t检验?

单样本的t检验 指样本的均值是否某个值存在差异。 比如一包薯片标的克重为50g&#xff0c;但每包不一定都是50g&#xff0c;那么我们可以对薯片进行随机抽样&#xff0c;检验它与50g是否有差异。 1 提出假设&#xff1a; 原假设&#xff1a;薯片的平均重量是50g&#xff1b; …

模板方法设计模式解读

目录 豆浆制作问题 模板方法模式基本介绍 基本介绍 模板方法模式的原理类图 模板方法模式解决豆浆制作问题 应用实例要求 思路分析和图解(类图) 模板方法模式的钩子方法 模板方法模式的注意事项和细节 豆浆制作问题 编写制作豆浆的程序&#xff0c;说明如下: 1) 制作豆…

Adobe认证是什么?

Adobe认证又称为Adobe国际认证(英文:Adobe Certified Professional)是Adobe公司CEO签发的权威国际认证体系&#xff0c;旨在为用户提供Adobe软件的专业认证。 Adobe认证包括产品技能认证和职业技能认证多个级别&#xff0c;从初学者到专业人士都可以参加。 Adobe认证覆盖了各…

ORA-27090故障,关于AIO-MAX-NR

在给某银行进行巡检时发现asm中的alert一直报ORA-27090错误。 通过巡检脚本&#xff0c;整理错误发生时间如下&#xff1a; 信息收集&#xff1a; 发生类似的错误&#xff0c;先收集alert日志的信息&#xff0c;操心系统的message日志。 Errors in file /u01/app/grid/diag/…

适合小白学习预处理与程序环境,这篇文章就够了

目录 一. 前言 二. 正文 2.1 “冷知识”&#xff1a;程序环境 2.21 翻译环境——程序从无到有&#xff1a;程序编译 链接 2.22 运行环境——程序开跑 2.3 那些鲜为人知&#xff1a;预定义符号 2.4 预处理指令 #define 2. 41 #和## —— 2.42 宏和函数优劣对比 2.…

阿里全新推出:微服务突击手册,把所有操作都写出来了

今天给大家带来的这份微服务是由阿里巴巴高级技术专家整理&#xff0c;针对Spring Cloud在国内的使用情况&#xff0c;结合国内上百家企业使用Spring Cloud落地微服务架构时遇到的问题和相应的解决方案结合成了这份电子版教程。&#xff08;文末有免费的获取方式&#xff09; …

火伞云APP盾,您身边的DDoS攻击安全保护专家

近年来全球各地区DDoS攻击的比例和次数在逐年增加&#xff0c;严重影响到网络信息安全。 主要有以下原因&#xff1a; 攻击成本低&#xff0c;攻击无壁垒。进行DDoS攻击成本很低&#xff0c;最低甚至只需要几百元就可以轻松发起一次攻击&#xff0c;然而被攻击的对象可能动辄…

3自由度并联绘图机器人实现写字功能(一)

1. 功能说明 本文示例将实现R305样机3自由度并联绘图机器人写字的功能。 2. 电子硬件 在这个示例中&#xff0c;采用了以下硬件&#xff0c;请大家参考&#xff1a; 主控板 Basra主控板&#xff08;兼容Arduino Uno&#xff09; 扩展板Bigfish2.1扩展板电池7.4V锂电池 3. 功能…

九种 OOM 常见原因及解决方案(IT枫斗者)

九种 OOM 常见原因及解决方案(IT枫斗者) 什么是OOM&#xff1f; OOM&#xff0c;全称“Out Of Memory”&#xff0c;翻译成中文就是“内存用完了”&#xff0c;来源于java.lang.OutOfMemoryError。看下关于的官方说明&#xff1a;Thrown when the Java Virtual Machine canno…

使用 Amazon SageMaker 构建文本摘要应用

背景介绍 文本摘要&#xff0c;就是对给定的单个或者多个文档进行梗概&#xff0c;即在保证能够反映原文档的重要内容的情况下&#xff0c;尽可能地保持简明扼要。质量良好的文摘能够在信息检索过程中发挥重要的作用&#xff0c;比如利用文摘代替原文档参与索引&#xff0c;可…

数据结构复习题(包含答案)

第一章 概论 一、选择题 1、研究数据结构就是研究&#xff08; D &#xff09;。 A. 数据的逻辑结构 B. 数据的存储结构 C. 数据的逻辑结构和存储结构 D. 数据的逻辑结构、存储结构及其基本操作 2、算法分析的两个主要方面是&#xff08; A …

Multi-modal Alignment using Representation Codebook

Multi-modal Alignment using Representation Codebook 题目Multi-modal Alignment using Representation Codebook译题使用表示子空间的多模态对齐期刊/会议CVPR 摘要&#xff1a;对齐来自不同模态的信号是视觉语言表征学习&#xff08;representation learning&#xff09;…

SpringMVC文件上传、异常处理、拦截器

SpringMVC文件上传、异常处理、拦截器 基本配置准备&#xff1a;maven项目模块 application.xml <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.…

数据库系统-数据物理存储

文章目录 一、DBMS原理1.1 DB物理存储1.1.1 磁盘的结构&特性1.1.2 DBMS数据存储&查询原理记录&#xff1a;磁盘块 1.2 DB文件组织方法1.2.1 无序文件组织1.2.2 有序记录文件1.2.3 散列文件(Hash File)1.2.4 聚簇文件(Clustering File) 1.3 Oracle 物理存储简介 一、DBM…

程序员最常见的谎言

小伙伴们大家好&#xff0c;我是阿秀。 上周看到知乎上有位网友总结了自己的10年程序员生涯中最常说的一些谎言&#xff0c;一共有15条&#xff0c;看完我直呼内行&#xff01;&#xff01; 全中&#xff01;每一枪都中了&#xff01;每一条我都说过。 我基本都说过他说过的那些…

下载VMware安装Ubuntu18.04.6系统

文章目录 前言&#xff1a;1. 下载VMWare与Ubuntu镜像2. 安装VMware3. VMware下安装Ubuntu 前言&#xff1a; 这篇文章是为交叉编译做的铺垫&#xff0c;本文内容比较简单&#xff0c;按步骤操作即可。 1. 下载VMWare与Ubuntu镜像 为了节约大家时间&#xff0c;省的各种找&am…

【Unity VR开发】结合VRTK4.0:摄像机碰撞变黑

语录&#xff1a; 人是要长大的&#xff0c;有天你也会推着婴儿车幸福地在街上行走&#xff0c;而曾经的喜欢&#xff0c;不管曾经怎样&#xff0c;都会幻化成风&#xff0c;消失在时光的隧道。所以向前走&#xff0c;向前走&#xff0c;无须回头。 前言&#xff1a; 往往我们在…

基于html+css的图片展示12

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

新品发布 | 智安网络【零信任SDP访问控制系统】正式上线!

近日&#xff0c;根据《2022年云办公行业研究报告》显示&#xff0c;2021-2023年&#xff0c;中国协同办公行业保持每年10%以上的增长率&#xff0c;远程办公人员的数量在过去十年中增长了115%&#xff0c;互联网时代已迎来远程办公需求大潮。 风口之下&#xff0c;员工对企业…

Go语言基础——通过获取网站API的cUrl,生成可直接执行的request代码(附:详细实战案例和源码)

作者&#xff1a;非妃是公主 专栏&#xff1a;《Golang》 博客地址&#xff1a;https://blog.csdn.net/myf_666 个性签&#xff1a;顺境不惰&#xff0c;逆境不馁&#xff0c;以心制境&#xff0c;万事可成。——曾国藩 文章目录 一、cUrl是什么&#xff1f;二、cUrl如何获取…