Spring事务传播机制、实现方式、失效场景即原理

贴一篇源码分析的好文章:https://blog.csdn.net/qq_30905661/article/details/114400417

本质:

一个事务对应一个数据库连接。
通过 this 来调用某个带有 @Transactional 注解的方法时,这个注解是失效的,可以看做这个方法(如上图B)上没有这个注解,当然书写的传播机制限制也是无效的,例如:propagation = Propagation.MANDATORY、propagation = Propagation.NEVER。
但是若调用A的是CGLIB生成的代理对象,并且A上有 @Transactional 注解,那么方法A是具有事务的,方法B中的sql 就在方法A的事务中执行,所以整体A,B是有事务的。

Spring的事务是如何实现的?

  1. spring事务底层是通过数据库事务和AOP实现的
  2. 首先对于使用@Transactional的注解的bean,spring会创建一个代理对象作为bean
  3. 当调用代理对象的方法时,spring会判断该方法上是否加了@Transactional注解
  4. 如果加了,就会利用事务管理器创建一个数据库连接,并修改数据库连接的 autocommit 为 false,禁止自动提交
  5. 然后执行该方法,若方法没有抛异常则会提交事务,反之亦然
  6. spring事物的隔离级别就是对应数据库的隔离级别
  7. spring事务的传播机制是spring自己实现的,是spring事务中最复杂的
  8. spring事物的传播机制是基于数据库连接来做的,一个连接一个事务,传播事务实际上是开了一个新的数据库连接,在此基础上执行sql

Spring事物的传播机制?

spring事务默认是注解是 REQUIRED,支持事务的传播,使用同一个数据库连接。
在这里插入图片描述

REQUIRED:spring默认的事务传播机制,A存在事务,则B加入A的事务;A没有事务则会新建一个数据库事务;

SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务;如果当前不存在事务,就以非事务执行

MANDATORY:(强制性使用第一个事务)A存在事务,则B加入A的事务;A没有事务,则抛异常

REQUIRES_NEW:创建一个新事务,B在这个新事务中执行;A如果有事务将会被挂起,等待B事务方法执行结束(commit or rollback),当B事务执行结束后,A事务被唤醒继续执行,若B抛出了异常给A 或 A 方法执行出了异常,那么在 A 事务中执行的 sql 将会被回滚,B 事务中的sql 由B的事务管理器控制,A、B中的sql不在同一数据库连接中执行,即内层事务B已经 commit 或 rollback, 外层事务干扰不了。

NOT_SUPPORTED:(不支持事务),若A存在事务,则挂起A的事务,以非事务方式运行

NEVER:(不支持事务),若A存在事务抛异常

NESTED:A存在事务,则在嵌套事务中执行;不存在则和 REQUIRED 一样开启一个新事务
在这里插入图片描述

那些情况会导致Spring事务的失效?失效的原因是?

  1. 数据库不支持事务

  2. 类没有被spring管理(ioc),没有加注解。

  3. 未启用Spring事务管理功能(@EnableTransactionManagement)

  4. 数据源没有配置事务管理器

    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource){return new DataSourceTransactionManager(dataSource);
    }
    
  5. 没有加@Configuration注解:springboot基本没有这个问题;Spring可能会出现这个问题,原因是由于mybatis或JdbcTemplate会从ThreadLocal中获取数据库连接,但是ThreadLocal底层引用的是ThreadLocalMap,Map的key是一个DataSource对象,value是数据库连接。如果没有加@Configuration注解的话,会导致Map中的DataSource对象和mybatis、jdbcTenplate中的DataSource对象不相等,所有就拿不到数据库连接,以至于自己去创建连接了。

  6. 异常被吃掉:默认情况下Spring会捕获 error 和 RunTimeException ,spring捕获不到异常也就不会回滚了,例如 try-catch

  7. 方法是private的:spring事务基于CGLIB来进行AOP,CGLIB是基于父子类来实现,子类是代理类,子类无法重写父类的private方法,也就没有办法增加spring事务逻辑。

  8. 方法是 final 修饰的,和private原因一致,子类不能重写增强。

  9. 调用A方法和B方法不是同一个线程,不同的线程拿到的数据库连接不一样。TransactionSynchronizationManager.bindResource 会将线程与数据库连接绑定。

  10. rollbackFor = RuntimeException.class(默认),当抛出的异常大于定义的异常,则会导致事务失效

  11. 方法内自调用时对象不是同一个:Spring事务是基于Aop,只有使用代理对象调用 A 方法时,注解才能生效,而在A方法中调用 B 方法时( this.B() ),并不是使用的代理对象,所以导致B的注解失效。

自身调用失效问题:

方法A 通过 this.B() 调用方法B。
在这里插入图片描述
本质:通过 this 来调用某个带有 @Transactional 注解的方法时,这个注解是失效的,可以看做这个方法(如上图B)上没有这个注解,当然书写的传播机制限制也是无效的,例如:propagation = Propagation.MANDATORY、propagation = Propagation.NEVER。
但是若调用A的是CGLIB生成的代理对象,并且A上有 @Transactional 注解,那么方法A是具有事务的,方法B中的sql 就在方法A的事务中执行,所以整体A,B是有事务的。

调用使用@Transactional注解的方法时,使用的是 Spring CGLIB 创建的代理对象
在这里插入图片描述

调用B方法的是存储在 Spring ioc容器的bean,两个不同的对象
在这里插入图片描述

A调用B的结论:

  • 只要A加@Transactional注解,A和B在不在同一个类中,B加不加@Transactional注解,事务都是有效的,则AB在同一事务中。
  • A 不加 B加,A和B同一个类中:调用A方法的是CGLIB生成的代理对象,但是A方法没有注解,所以A方法不会被拦截;this调用B,注解失效(下图)。
  • A 不加 B加,A和B不在同一个类中:不在同一个类,那么调用B的就是的就是CGLIB生成的代理对象,B的事务有效,A在外围没有事务(B已经commit或rollback了,事务管理器已经把设置auto commit = false的数据库连接释放了)。

图3

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

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

相关文章

Cocos Creator不规则按钮

实现该功能需要用到组件PolygonCollider2D,官方链接: https://docs.cocos.com/creator/3.4/manual/zh/physics-2d/physics-2d-collider.html 创建组件 创建一个精灵节点: 创建碰撞组件PolygonColider2D,如图 给按钮添加多边形碰…

链表的总体涵盖以及无哨兵位单链表实现——【数据结构】

😊W…Y:个人主页 在学习之前看一下美丽的夕阳,也是很不错的。 如果觉得博主的美景不错,博客也不错的话,关注一下博主吧💕 在上一期中,我们说完了顺序表,并且提出顺序表中的问题 1. 中…

无涯教程-Lua - 函数声明

函数是一起执行任务的一组语句,您可以将代码分成单独的函数。 Lua语言提供了程序可以调用的许多内置方法。如方法 print()打印在控制台中作为输入传递的参数。 定义函数 Lua编程语言中方法定义的一般形式如下- optional_function_scope function function_name(…

一个SpringBoot 项目能处理多少请求?

这篇文章带大家盘一个读者遇到的面试题哈。 根据读者转述,面试官的原问题就是:一个 SpringBoot 项目能同时处理多少请求? 不知道你听到这个问题之后的第一反应是什么。 我大概知道他要问的是哪个方向,但是对于这种只有一句话的…

Django实现音乐网站 ⑵

使用Python Django框架制作一个音乐网站,在系列文章1的基础上继续开发,本篇主要是后台歌手表模块开发。 目录 表结构设计 歌手表(singer)结构 创建表模型 设置图片上传路径 创建上传文件目录 生成表迁移 执行创建表 后台管…

代理模式.

前言: 为什么要学习代理模式,因为AOP的底层机制就是动态代理! 代理模式: 静态代理 动态代理 静态代理 抽象角色 : 一般使用接口或者抽象类来实现 真实角色 : 被代理的角色 代理角色 : 代理真实角色 ; 代理真实角色后 , 一…

艺术二维码 API 申请及使用

艺术二维码是一种创新的技术产品,它将二维码与美观的背景图像相结合,创造出既实用又美观的作品。它们不仅具有传统二维码的功能性,能被智能设备快速扫描识别,还加入了艺术元素,增强了视觉吸引力和品牌识别度。其中&…

ffmpeg综合应用示例(五)——多路视频合并(Linux版本)

本文的目的为方便Linux下编译运行多路视频合成Demo 原文:ffmpeg综合应用示例(五)——多路视频合并 Ubuntu 20.04 ffmpeg version ffmpeg-4.4-x86_64 编译 export LD_LIBRARY_PATH$LD_LIBRARY_PATH:/home/workspace/dengzr/linux-x64/lib…

jenkins使用gitlab标签发布

关于jenkins git parameter使用gitlab标签发布和分支发布的用法 手动配置的我就不说了,点点点就行,主要是说一下在pipeline里如何使用 通过分支拉取gitlab仓库代码 pipeline {agent anyenvironment {}parameters {gitParameter(branch: , branchFilte…

Sentinel dashboard的使用;Nacos保存Sentinel限流规则

Sentinel dashboard的使用 往期文章 Nacos环境搭建Nacos注册中心的使用Nacos配置中心的使用Sentinel 容灾中心的使用 参考文档 Sentinel alibaba/spring-cloud-alibaba Wiki GitHub 限流结果 下载sentinel-dashboard github地址:Sentinel/sentinel-dashboar…

prototype, construction, instanceof

prototype 属性的作用 JavaScript 规定,每个函数都有一个prototype属性,指向一个对象。 function f() {} typeof f.prototype // "object" ​ 上面代码中,函数f默认具有prototype属性,指向一个对象。 对于普通函数来…

【雕爷学编程】MicroPython动手做(28)——物联网之Yeelight 4

知识点:什么是掌控板? 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片,支持WiFi和蓝牙双模通信,可作为物联网节点,实现物联网应用。同时掌控板上集成了OLED…

C++之观察者模式(发布-订阅)

目录 模式简介 介绍 优点 缺点 代码实现 场景说明 实现代码 运行结果 模式简介 观察者模式(Observer Pattern),也叫我们熟知的发布-订阅模式。 它是一种行为型模式。 介绍 观察者模式主要关注的是对象的一对多的关系, …

Go和Java实现组合模式

Go和Java实现组合模式 我们通过部门和员工的层次结构的示例来演示组合模式的用法。 1、组合模式 组合模式,又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对 象,用来表示部分以及整体层次。这种…

【MFC】03.常用复杂控件的使用-笔记

热键: 对话框-类向导:初始化函数中,热键需要在最开始的时候就注册进去: 注册热键: 在这之前,先去定义一个宏,代表你这个快捷键。 参数:窗口句柄,热键编号(热…

antd vue中遍历v-for中控制每个按钮的loading

项目中遇到一个需求&#xff0c;需要根据后台返回数据&#xff0c;遍历生成多个按钮&#xff0c;并点击出发事件。点击事件的时候需要该按钮loading状态。实现方法如下&#xff1a; <div class"center"><a-button v-for"(item,index) in btnItems&quo…

C# File.Exists与Directory.Exists用法

File.Exists&#xff1a; 用于检查给定文件路径是否存在。如果文件存在&#xff0c;则返回true&#xff0c;否则返回false。 string path“D:\\test\\example.txt” bool exists File.Exists(path); if (exists) {Console.WriteLine("File exists."); } else {Con…

Qt 实现压缩文件、文件夹和解压缩操作zip

一、实现方式 通过Qt自带的库来实现&#xff0c;使用多线程方式&#xff0c;通过信号和槽来触发压缩与解压缩&#xff0c;并将压缩和解压缩结果回传过来。 使用的类&#xff1a; #include "QtGui/private/qzipreader_p.h" #include "QtGui/private/qzipwriter…

HCIP入门静态实验

题目及要求 第一步&#xff1a;拓扑的搭建 第二步&#xff1a;路由、IP的配置 r1: <Huawei>sys Enter system view, return user view with CtrlZ. [Huawei]sys r1 [r1]int loop [r1]int LoopBack 0 [r1-LoopBack0]ip add 192.168.1.65 27 [r1-LoopBack0]int loop 1 […

什么是高级持续威胁(APT)攻击

目录 前言什么是高级持续威胁高级持续威胁攻击有哪些独特特征APT攻击的五个阶段APT检测及防护措施总结 前言 APT攻击是利用多个阶段和不同攻击技术的复合网络攻击。APT不是一时兴起构思或实施的攻击。相反&#xff0c;攻击者故意针对特定目标定制攻击策略。并在较长时间内进行…