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

news2024/11/15 11:12:30

贴一篇源码分析的好文章: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.coloradmin.cn/o/833159.html

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

相关文章

Windows下安装Zookeeper(图文记录详细步骤,手把手包安装成功)

Windows下安装Zookeeper 一、下载Zookeeper安装包1.1、官网下载Zookeeper1.2、网盘下载Zookeeper 二、解压Zookeeper安装包到指定目录三、Zookeeper安装目录下创建文件夹四、进入config目录五、复制zoo_sample.cfg文件,改名为zoo.cfg六、修改配置文件 zoo.cfg七、添…

Nodejs的fs模块的基础应用

fs模块是Node.js中内置的用于文件系统操作的模块,它提供了各种方法和函数,用于处理文件和目录。 目录 1.写入文件 2.讲讲同步和异步 3.追加写入 4.读取文件 5.文件重命名及文件移动 6.文件删除 7.文件夹的操作 1.写入文件 普通的写入方法&#x…

智能制造企业如何建立大客户管理模型?

01、大客户管理依然是智能制造企业经营的黄金定律 《连线》杂志创始人凯文凯利(Kevin Kelly)在《技术元素》一书中写道:“数量不是目的,质量才是根本,重视1%的超级用户才是提高效率的关键。” 根据“二八定律”&…

Arduino驱动MQ4模拟甲烷气体传感器(气体传感器篇)

目录 1、传感器特性 2、硬件原理图 3、驱动程序 MQ4气体传感器,可以很灵敏的检测到空气中的甲烷、天然气等气体,但是对乙醇和烟雾的灵敏度很低。与Arduino结合使用,可以制作火灾甲烷、天然气泄露报警等相关的作品。 1、传感器特性 MQ4对不同种类、不同浓度的气体有不同的…

SystemVerilog数组参数传递及引用方法总结

一、将常数数组传递给task/function 如下面的程序,将一个常数数组传递给function module my_array_test();function array_test(int array[4]);foreach(array[i]) begin$display("array[%0d] %0d", i, array[i]);endendfunctioninitial beginarray_tes…

@Transactional详解(作用、失效场景与解决方法)

一、了解Transactional注解,先要知道事务是什么,但既然知道了这个注解,不知道事务是什么,那就重新再去学习一遍数据库吧,这里讲解开发中代码实现事务的方式 1、编程式事务(开发用的很少了) 基于…

【火炬之光-召唤装备】

头部胸甲手套鞋子武器盾牌项链戒指腰带神格备注*邪龙头冠无限要塞/血抗血抗血抗***终焉复临任意攻速单手武器/黑峡烬盾1召唤等级血抗*原点的寒冬1召唤等级1.刷钢铁炼境监视者-无垢之墙升级。2.不能用典狱官的胸针参考视频机械领主无限要塞––***终焉复临––求生之欲––参考视…

Zoho CRM有哪些功能?使用体验如何?

市场上有很多CRM品牌,但是Zoho CRM是比较亮眼的存在,不仅屡获CRM国际大奖,更是连续十一年入选Gartner魔力象限。不论是功能、价格还是使用体验,都备受用户青睐。下面我们就来说说,Zoho CRM的使用体验评价。 Zoho CRM有…

Codeforces Round 888 (Div. 3)F题题解

文章目录 [Lisa and the Martians](https://codeforces.com/contest/1851/problem/F)问题建模问题分析1.分析给定的运算操作2.方法1使用Trie树来查找最符合的数代码 方法2通过性质,排序后找运算的最大值代码 证明 Lisa and the Martians 问题建模 ​ 给定n个数和k&…

如何搭建一个口才培训的网站?需要具备哪些条件?

论文题目:如何搭建一个口才培训的网站及所需条件 摘要: 本文探讨了如何搭建一个口才培训的网站,并详细分析了所需的关键条件。口才培训作为一种重要的社交技能,能够帮助人们提升自信和影响力,因此具有广阔的市场前景。…

【yolov5训练报错Wandb wandb.errors.UsageError: api_key not configured (no-tty).】

跑yolov5训练官方代码出现下面的问题,第一个方法就是关闭代理网络vpn,直接运行,阻止数据上传。 D:\anaconda\envs\yolov5\python.exe C:\Users\ljx\Desktop\yoloair-main\yoloair-main\yolov7\train.py YOLOR 2022-11-8 torch 1.8.1cu111…

Nginx 高性能内存池 ----【学习笔记】

跟着这篇文章学习: c代码实现一个高性能内存池(超详细版本)_c 内存池库_linux大本营的博客-CSDN博客https://blog.csdn.net/qq_40989769/article/details/130874660以及这个视频学习: nginx的内存池_哔哩哔哩_bilibilihttps://w…

TikTok马来西亚站变动,指定物流服务商!

8月2日,据TechinAsia报道,TikTok已将百世快递在马来西亚的子公司BestExpressMalaysia,指定为其在马来西亚的物流服务商。目前,百世快递已在越南、泰国与TikTok展开类似合作。 合作后,百世马来子公司将为TikTokShop卖家…

js去除字符串中特殊字符并将数据转为数组格式

let str今-天-空-气-很-清-新;let liststr.split(-);console.log(list)使用split将特殊字符去除并将数据转为数组

解决vite+vue3项目npm装包失败

报错如下: Failed to remove some directories [ npm WARN cleanup [ npm WARN cleanup D:\\V3Work\\v3project\\node_modules\\vue, npm WARN cleanup [Error: EPERM: operation not permitted, rmdir D:\V3Work\v3project\node_modules\vue\reactivity\…

Spring @Scheduled单线程单实例的坑

文章目录 前言背景验证解决方案 前言 在 Java Spring 项目中经常会用 Scheduled 来实现一些定时任务的场景,有必要了解一些它使用时的问题和内部实现机制。本文是偶然间发现的一个问题,刷新了我的认知,分享给大家。 其他相关文章&#xff1…

Pytorch深度学习-----神经网络之Sequential的详细使用及实战详解

系列文章目录 PyTorch深度学习——Anaconda和PyTorch安装 Pytorch深度学习-----数据模块Dataset类 Pytorch深度学习------TensorBoard的使用 Pytorch深度学习------Torchvision中Transforms的使用(ToTensor,Normalize,Resize ,Co…

产品经理之路:从C端到B端的崭新旅程

理解C端和B端 在我们开始探讨从C端产品经理到B端产品经理的转变之前,我们首先需要理解C端和B端是什么,以及它们之间有什么区别。 C端产品与B端产品的基本区别 C端产品(Consumer端产品)是面向普通消费者的产品,如社交…

大数据课程F4——HIve的其他操作

文章作者邮箱:yugongshiyesina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 掌握HIve的join; ⚪ 掌握HIve的查询和排序 ⚪ 掌握HIve的beeline ⚪ 掌握HIve的文件格式 ⚪ 掌握HIve的基本架构 ⚪ 掌握HIve的优化; 一、jo…

一个对象的内存图,两个对象使用同一个方法的内存图

一个对象的内存图 public class Phone {String brand; //品牌double price; //价格String color; //颜色public void call(String who) {System.out.println("给" who "打电话");}public void sendMessage() {System.out.println("群发短信");…