Spring事务(事务的实现、隔离级别、传播机制)

news2024/9/27 12:11:48

目录

 一、事务的定义和意义

二、事务的实现

1、MySQL事务的回顾

2、Spring声明式事务(利⽤注解⾃动开启和提交事务)

前置知识及概念

实例分析:事务的回滚

🔔特殊情况(无自动回滚)

🔔事务不会⾃动回滚解决⽅案

🔔@Transactional工作原理

@Transactional 实现思路预览:  

三、Spring事务传播机制 

1、事务的隔离级别及传播机制的引入

2、事务的传播机制

3、事务的隔离级别和事务的传播机制的区别


 一、事务的定义和意义

事务的定义

将⼀组操作封装成⼀个执⾏单元(封装到⼀起),要么全部成功,要么全部失败。

简单来说:事务诞生的目的就是为了把若干个独立的操作给打包成一个整体。



我们需要注意的是: Spring 的事务 相比于 MySQL 中的事务,要复杂一些!

MySQL 的事务 无非就是 事务可以并发执行,需要考虑隔离性的问题。
但是!MySQL 的事务 非常单纯!
它不会说出现事务嵌套的问题。
比如:事务 A 嵌套了 事务 B,事务 B 嵌套了 事务 C,事务 C。。。。。
这种情况,在MySQL事务中是不会出现的。

Spring 的事务,就大不一样了!

因为我们代码,通常完成一个业务逻辑(事务),需要调用多个方法(事务),才能执行。
而多个多个方法又可能依赖于其他的方法,才得以实现。
这种情况,在 代码中 是非常常见的。

如果程序中出现这中嵌套的现象的话。
没问题的话,那还好,没有问题,
但是!万一出现了问题,那我们其它事务(方法)应该怎么去处理呢?

是相互不影响吗? 一个事务(方法)出现了问题,其它的事务不受影响。
还是 “引火上身”呢?一个事务牵扯到 ABC 三个事务,如果 一个事务出现了问题,其它的事务是是无法执行的,直接给你 进行 事务回滚了!

这个就涉及到 Spring 事务传播的机制是怎么设置的了
 

二、事务的实现

1、MySQL事务的回顾

详见MySQL的索引与事务(面试必考) - 细节狂魔_Dark And Grey的博客-CSDN博客

2、Spring声明式事务(利⽤注解⾃动开启和提交事务)

前置知识及概念

Spring 中的事务操作分为两类:

1、编程式事务(⼿动写代码操作事务)
编程式事务:通过代码来控制事务的 开启 和 提交,或者是 回滚。

2、 声明式事务(利用注解自动开启和提交事务)

声明式事务的实现很简单,只需要在需要的⽅法上添加 @Transactional 注解就可以实现了,⽆需⼿动开启事务和提交事务,进⼊⽅法时⾃动开启事务,⽅法执⾏完会⾃动提交事务,如果中途发⽣了没有处理的异常会⾃动回滚事务

默认情况下,只有来自外部的方法调用才会被AOP代理捕获,也就是,类内部方法调用本类内部的其他方法并不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰。

@Transactional 可以⽤来修饰⽅法或类:

  • 修饰⽅法时:需要注意只能应⽤到 public ⽅法上,否则不⽣效。推荐此种⽤法。
  • 修饰类时:表明该注解对该类中所有的 public ⽅法都⽣效。

Spring的事务管理默认是针对***unchecked exception**回滚,也就是默认对Error异常和RuntimeException异常以及其子类进行事务回滚,且必须抛出异常,若使用try-catch对其异常捕获则不会进行事务回滚操作

因此

  • 对于unchecked exception(Error和RuntimeException异常)抛出时不需要方法调用throws或try-catch语句
  • 而checked exception 则必须用try语句块进行处理或者把异常交给上级方法处理,总之就是必须写代码处理它,所以必须在service捕获异常,然后再次抛出,这样事务方才起效。

关于异常详情见:异常

实例分析:事务的回滚

 我们通过url模拟添加操作

那么如果出现了异常,数据库中会不会添加这一条就记录呢?

 可以看到,我们再浏览器的url输入的lisi这条记录,没有成功添加到数据库中。

原因就是@Transactional 注解的自动回滚操作——》通过该注解,我们⽆需⼿动开启事务和提交事务,进⼊⽅法时⾃动开启事务,⽅法执⾏完会⾃动提交事务,如果中途发⽣了没有处理的异常会⾃动回滚事务

🔔特殊情况(无自动回滚)

我们再浏览器里继续上面的操作(尝试添加一条lisi的记录,看看有什么变化)

 

可以看到数据库中有了lisi这条数据——》@Transactional 在异常被捕获的情况下,不会进⾏事务⾃动回滚。

🔔事务不会⾃动回滚解决⽅案

  • 解决⽅案1:对于捕获的异常,事务是会⾃动回滚的,因此解决⽅案1就是可以将异常重新抛出
  • 解决⽅案2:⼿动回滚事务,在⽅法中使⽤ TransactionAspectSupport.currentTransactionStatus() 可以得到当前的事务,然后设置回滚⽅法 setRollbackOnly 就可以实现回滚

🔔@Transactional工作原理

@Transactional 是基于 AOP 实现的,AOP ⼜是使⽤动态代理实现的。如果⽬标对象实现了接⼝,默认情况下会采⽤ JDK 的动态代理,如果⽬标对象没有实现了接⼝,会使⽤ CGLIB 动态代理。
@Transactional 在开始执⾏业务之前,通过代理先开启事务,在执⾏成功之后再提交事务。如果中途遇到的异常,则回滚事务。

@Transactional 实现思路预览:  

三、Spring事务传播机制 

1、事务的隔离级别及传播机制的引入

Spring 中事务隔离级别包含以下 5 种

1. Isolation.DEFAULT:以连接的数据库的事务隔离级别为主。
2. Isolation.READ_UNCOMMITTED:读未提交,可以读取到未提交的事务,存在脏读。
3. Isolation.READ_COMMITTED:读已提交,只能读取到已经提交的事务,解决了脏读,存在不可重复读。
4. Isolation.REPEATABLE_READ:可重复读,解决了不可重复读,但存在幻读(MySQL默认级别)。
5. Isolation.SERIALIZABLE:串⾏化,可以解决所有并发问题,但性能太低

从上述介绍可以看出,相⽐于 MySQL 的事务隔离级别,Spring 的事务隔离级别只是多了⼀个
Isolation.DEFAULT(以数据库的全局事务隔离级别为主)

 

 为什么需要事务的传播机制

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

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

我们之前学习的事务都很简单,都是单个的事务。
各个事务之间是没有关联关系,并且不存在相互调用的情况。
但是!这种美好的情况,只是发生在 我们学习 Spring 框架之前。
之前我们的事务 是在数据库里面去操作的,没有问题!
单个事务,很简单。很纯粹!

但是呢,我们现在到了具体的业务方法里面,具体框架里面,它的业务场景就会变成复杂很多!
就比如:A方法调用 B 方法,B方法里面又调用了 C 方法。。。。
ABC。。。都有事务.
现在问你: 事务,它应该怎么样进行传递 和 怎么样去执行。
是每个事务各自运行,互不影响;

还是几个事务 组成一个大事务;

还是说,我不以事务的方式执行。
这种可能性是完全可能存在的。
比如:
A 调用 B,B 调用 C,C 调用 D.
然后呢,A有事务,B有事务,C 没事务,D 有事务。
好,这个时候,我们该怎么办?
我的事务要不要传,毕竟 C 没有事务,中间 “ 断了 ”。
这样的话,情况就异常复杂了。
这就是一个应用级程序 的 特性。
这东西很复杂!
因为 它没有那么纯粹,没有那么简单!
这时就用到我们事务的传播机制了

2、事务的传播机制

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

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

 

1、 Propagation.REQUIRED:
默认的事务传播级别,它表示如果当前存在事务,则加⼊该事务;如果当前没有事务,则创建⼀个新的事务。

这就跟现在结婚的现状是一样的,房子(事务)是必须项、
女方就是 隔离级别 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(创建一个新事物)。

这种就是 白富美剧情。
男方有房,女方家里又给了一套房。
如果男方没有房,女方家里表示我可以送一套!

 

 

REQUIRED需要有(事务的默认传播机制)和NESTED嵌套事务的区别:

1) REQUIRED需要有他是如果当前方法存在事务,把当前方法的事务加入到之前的那个事务当中,一荣俱荣,一损俱损(两个事务直接是一个整体,如果其中有任何一个事务有问题,这两个事务作为一个整体都不会执行)——》所有是事务都加到了一个大的事务里面了。

2) NESTED嵌套事务则不同,事务直接不是一个整体,是相互嵌套着的。如果当前存在事务,把当前事务嵌套到之前的事务中来这些,如果当前事务存在异常(只是影响发生异常的这一个事务,不影响其他事务)

3、事务的隔离级别和事务的传播机制的区别

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

事务隔离级别解决的是多个事务同时调⽤⼀个数据库的问题

 

 

 事务传播机制解决的是⼀个事务在多个节点(⽅法)中传递的问题(或多个事务的嵌套和互相加入)

 如果是多个事务,在相互调用的情况,也很好理解!
事务的传播机制,在多个事务相互调用的时候,对其进行“行为控制”,让其结果能够达到我们预期的效果。

 

我们还可以发现,在事务的传播机制中,多个事务都在 “一条线上”。

那么,问题来了:
正如我们前面所说: 如果这三个事务中,有一个事务 只是一个普通方法,不具备事务。使其 事务的传递 中断,我们该怎么做?

是全部回滚,将数据恢复到未操作状态。
还是说,那个事务出现了问题,就回滚那个事务。
或者,不回滚。

这些都是不确定的因数!
这些都是:婆说婆有理,公说公有理。
无论你怎么说,你都有你的道理。

但是!不管怎么说,我们都需要一个统一行为,或者说 一个统一的管理模式。【放在上面例子中,就是要有一个 客观的标准】

这就必须要依靠事务传播机制,依靠 设置 和 规定,来去处理。

参考文章:

SpringBoot 使用 @Transactional 注解配置事务_深寒色的猫丶的博客-CSDN博客

 JavaEE进阶 - Spring事务和事务传播机制 - 细节狂魔_java事务传播机制_Dark And Grey的博客-CSDN博客

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

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

相关文章

VueJs中如何使用provide与inject

前言在vue2.0里面provide与inject是以选项式(配置)API的方式在组件中进行使用的,解决的是跨组件(祖孙)间通信的一种方式也就是父子组件间的通信,父组件上通过自定义属性,而子组件间通过props这种方式接收,如果想要一层一层的传递,这种方式就会比较麻烦,不灵活provide与inject就…

Linux下的进程信号

目录 信号背景: 信号产生前 Core Dump 信号产生中 信号产生后 其他概念 不可重入函数 volatile关键字 SIGCHLD 17号信号 信号背景: 在生活中处处都存在的信号,比如信号灯,要想处理信号,我们就必须具备两种…

day26-XML/枚举/注解

1.xml 1.1概述【理解】 万维网联盟(W3C) 万维网联盟(W3C)创建于1994年,又称W3C理事会。1994年10月在麻省理工学院计算机科学实验室成立。 建立者: Tim Berners-Lee (蒂姆伯纳斯李)。 是Web技术领域最具权威和影响力的国际中立性技术标准机构。 到目前为…

AWS - IAM

AWS IAM 自用笔记。 Terms IAM - Identity and Access Management, a global service it gives: Centralized control of AWS accountShared access to AWS accountGranular permissionsIdentity Federation, i.e., Facebook, LinkedIn etc. it allows: Multi-Factor Authe…

20230121解决AIO-3568J开发板无法刷机以及串口异常的问题

20230121解决AIO-3568J开发板无法刷机以及串口异常的问题 2023/1/21 22:31 一片比较旧的AIO-3568J开发板,症状: 1、无法刷机&启动。【Loader模式 & MASKROM模式】 2、串口输出乱码! (一)刷机问题的解决&#x…

一起自学SLAM算法:7.3 估计理论

连载文章,长期更新,欢迎关注: 不管是用贝叶斯网络还是因子图,一旦SLAM问题用概率图模型得到表示后,接下来就是利用可观测量(和)推理不可观测量(和),也就是说S…

初识C语言(上)

写在前面 我们正式开始接触到C语言,这是我在学习过C语言后重新写的博客,我把之前的稍微优化了一下,希望能用更加朴素的语言和大家分享,我希望给大家带来一个可以看的懂,理论和实践并行的内容.当然里面也会存在一些错误和不恰当的地方,还请诸位指正. 为何学习C语言 我想从两个…

mac 疑难问题汇总

macos 更改zsh到bash查看当前系统有哪些bash命令行:cat /etc/shells切换成bash命令行:chsh -s /bin/bashmac触摸屏轻点设置Mac通过crontab设置定时任务报错Operation not permitted1、系统偏好设置->安全性和隐私->完全磁盘访问权限2、解除锁定允许…

【双向链表】java代码实现

前言: 大家好,我是良辰丫🍓🍓🍓,上一篇文章我和大家一起去探索了单链表的知识世界,今天我们去接触双向链表,什么?没听错,就是双向链表,比单链表更…

UE INI文件操作 INI File Operation [ Read / Write ] 插件说明

在 Windows 平台上的 INI 文件读写操作 1. Write INI String 输入: Directory: 选择保存目录 Project Directory : 当前项目目录Project Content Directory:当前项目 Content 目录Project Config Directory:当前项目…

JVM内存区域的划分

根据 JVM 规范,JVM 内存共分为虚拟机栈、堆、方法区、程序计数器、本地方法栈五个部分。 程序计数器(线程私有): 是当前线程所执行的字节码的行号指示器,每条线程都要有一个独立的程序计数器,这类内存也称为…

Java基础08:面向对象进阶(上)

Java基础08:面向对象进阶(上)一、static1. 静态变量2. 静态方法3. 工具类4. static注意事项5. 重新认识main方法二、继承1. 继承的概念2. 继承的特点3. 继承中访问成员变量4. 继承中访问成员方法(方法重写)5. 继承中访…

给大家准备了程序员专属红包封面,审核通过后我哭了,太心酸了(┬_┬)

大家好,我是小悟 今天就是除夕了,也就是大年三十,小伙伴们应该都回家了吧,小悟祝大家新年快乐,身体健康,万事如意,兔飞猛进哦。 春节临近,收到微信定制红包封面并送了四千个名额的…

【深度学习】详解 MoCo

目录 摘要 一、引言 二、相关工作 三、方法 3.1 Contrastive Learning as Dictionary Look-up 3.2 Momentum Contrast 3.3 Pretext Task 四、实验 4.1 Linear Classification Protocol 总结 ☆ 实现 参考资料 Title:Momentum Contrast for Unsupervised…

AlmaLinux 9 安装Kasm Workspaces

今天尝试一下AlmaLinux 9 安装Kasm Workspaces。 前提条件 安装了Docker和Docker Compose,已经最新版本要求, docker 18.06 docker compose 2.1.1 创建一个Swap分区 下面的步骤将创建一个2千兆字节(2048MB)的交换分区。请根据…

我的创作纪念日——“永远相信美好的事情即将发生”

作者:非妃是公主 专栏:《程序人生》 个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩 文章目录序与CSDN的往事机缘收获憧憬碎碎念序 第一次写创作纪念日的文章!哈哈哈哈,今…

一起自学SLAM算法:7.5 基于因子图的状态估计

连载文章,长期更新,欢迎关注: 虽然式(7-90)所示的完全SLAM系统可以用滤波方法求解,比如著名的Fast-SLAM实现框架。但是,贝叶斯网络表示下的完全SLAM系统能很方面地转换成因子图表示,…

字符串匹配: BF与KMP算法

文章目录一. BF算法1. 算法思想2. 代码实现二. KMP算法1. 算法思想概述2. 理解基于最长相等前后缀进行匹配3. 代码中如何实现next数组5. 代码实现6. next数组的优化一. BF算法 1. 算法思想 BF 算法, 即暴力(Brute Force)算法, 是普通的模式匹配算法, 假设现在我们面临这样一个…

24/365 java 观测线程状态 线程优先级

1.观测线程 JDK中定义的线程的六个状态 &#xff1a; 可以用getState()来观测线程 public static void main(String[] args) throws InterruptedException {Thread thread new Thread(()->{for (int i 0; i < 10; i) {try {Thread.sleep(100);} catch (InterruptedExc…

2023适合新手的免费编曲软件FL Studio水果21中文版

水果软件即FL Studio&#xff0c;这是一款较为专业的编曲软件&#xff0c;这款软件自带高品质打击乐、钢琴、弦乐以及吉他等107种乐器效果&#xff0c;内置了包括经典电子音色、合成利器3xosc、sytrus、slicex等多种插件&#xff0c;可以帮助音乐制作人创作不同的音乐曲风&…