Spring5应用之事务属性
作者简介:☕️大家好,我是Aomsir,一个爱折腾的开发者!
个人主页:Aomsir_Spring5应用专栏,Netty应用专栏,RPC应用专栏-CSDN博客
当前专栏:Spring5应用专栏_Aomsir的博客-CSDN博客
文章目录
- 参考文献
- 前言
- 事务属性
- 什么是事物属性?
- 如何添加事务属性?
- 隔离属性
- 脏读
- 解决方案
- 不可重复读
- 解决方案
- 幻影读
- 解决方案
- 注意事项
- 传播属性
- 解决方案
- 只读属性
- 超时属性
- 异常属性
- 总结
参考文献
- 孙哥suns说Spring5~学不会Spring? 因为你没找对人~孙帅
- Spring官方文档
前言
在前两篇文章中,我们深入探索了Spring与MyBatis的整合技术,并详细讨论了Spring在事务处理方面的能力。今天,我决定进一步深入研究Spring,在事务属性上进一步的深入研究
事务属性
什么是事物属性?
事务属性是用来描述事务特性的一组值。主要包括隔离属性
、传播属性
、只读属性
、超时属性
和异常属性
。通过这些属性,我们可以全面地描述和管理事务的行为
如何添加事务属性?
在上一篇文章中,我们已经探讨了如何在原始方法的类或方法上使用@Transaction注解
来定义事务的切入点。要设置事务属性,我们只需在这一注解中配置相应的属性值。例如,isolation用于指定隔离级别,propagation表示传播行为,readOnly标识该事务是否为只读,rollbackFor定义哪些异常会触发事务回滚,而timeOut指定事务的超时时间。接下来,我们会详细解析每一个属性的具体值和含义,以帮助大家更深入地理解和使用事务属性
隔离属性
隔离属性主要描述了事务如何解决数据库事务并发操作中的问题。在此之前,我们首先要明确什么是并发,以及并发中可能会遇到哪些问题,以及如何解决这些问题。
什么是并发? 并发是指多个事务在同一时刻,对相同的数据进行访问和操作。
并发会产生哪些问题? 并发操作中可能出现的问题包括脏读
、不可重复读
和幻影读
。
并发问题如何解决? 并发中的问题可以通过设定合适的隔离属性来解决。根据隔离属性的不同值,我们可以有效地避免或解决在并发处理过程中出现的这些问题
脏读
所谓脏读,是指一个事务读取到了另一个事务尚未提交的数据,这种操作可能导致当前事务中的数据不一致。想象一个场景:如果事务的隔离级别设置得不够高,它可能会读取到另一事务已修改但尚未提交的数据。如果在此基础上,我们对这份数据进行了进一步的修改、添加或删除,而后来那个外部事务决定回滚,那么当前事务所做的所有操作都可能变得无效或导致数据错误
解决方案
为了避免脏读,可以将事务的隔离属性设置为“读已提交
”。这样,事务只能读取其他事务已经提交的数据,从而确保数据的一致性。在代码中,这可以通过以下注解属性来实现:
@Transaction(isolation=Isolation.READ_COMMITTED)
不可重复读
所谓不可重复读,是指在同一个事务内多次读取相同数据时,得到的结果不同。举个例子,假设在事务A中,第一次查询某数据得到的结果是1000。而在事务A的两次查询之间,另外一个事务B将这个数据减少了200。当事务A再次查询时,得到的结果就变成了800,从而导致事务A中出现了数据不一致的情况
解决方案
为了避免不可重复读的问题,我们可以将事务的隔离属性设置为“可重复读
”。这样的设置确保在事务执行过程中,对同一数据的多次读取都能获得一致的结果。在代码中,可以通过以下注解属性来实现:
其本质是为相关数据加上行锁,确保在当前事务执行期间,其他事务不能修改这部分数据
@Transaction(isolation=Isolation.REPEATABLE_READ)
幻影读
所谓幻影读,是指在同一个事务中对整张表进行多次统计查询时,得到的结果各不相同,从而在事务内产生数据不一致的问题
解决方案
为了避免幻影读的问题,我们可以将事务的隔离属性设置为“串行化”(SERIALIZABLE)。这样的设置可以确保在事务执行过程中,对整张表的多次统计查询都能获得一致的结果。在代码中,可以通过以下注解来实现:
其核心机制是为整张表加上表锁,确保在当前事务执行期间,其他事务不能对此表进行添加或删除操作。
@Transaction(isolation=Isolation.SERIALIZABLE)
注意事项
- 数据库默认隔离级别: Spring提供的事务属性默认值会根据不同类型的数据库的默认隔离级别进行动态选择。
- 灵活选择隔离属性: 在实际应用中,我们应当灵活地选择隔离属性。根据具体的业务需求,选择合适的隔离属性,当然,默认的设置通常也是推荐的。
- 解决并发问题: 在实战中遇到并发问题时,常用的解决方法是采用悲观锁。例如,可以使用JPA的Version或者通过MyBatis的拦截器进行自定义开发
传播属性
传播属性主要描述了如何解决事务嵌套的问题。事务嵌套发生在一个主事务中包含多个子事务的情况。
例如,当AService中的a方法启动一个事务时,这个a方法可能会调用BService的b方法和CService的c方法,这两个方法都各自拥有独立的事务,这种情况下就构成了事务嵌套。这样的嵌套可能导致各个子事务之间相互影响,进而使主事务失去其原子性。
通过正确地设置传播属性,我们可以确保在整个操作过程中只存在一个统一的事务。
解决方案
当我们需要设定事务的传播行为,可以在事务注解中添加propagation属性
。各个传播属性的具体值及其含义可以参考下表。
在实际开发中,REQUIRED
和SUPPORTS
这两个传播属性可以解决99%的场景需求。
默认的传播属性是REQUIRED,因此对于增、删、改的方法,我们通常不需要手动设置。而对于查询方法,我们则需要手动将其传播属性设置为SUPPORTS
只读属性
对于仅涉及查询操作的业务方法,我们可以添加只读属性,从而优化运行效率。这可以通过readOnly属性
来实现。虽然它的默认值是false,但在需要的时候,我们可以手动开启它,使查询操作更加高效
超时属性
超时属性定义了事务执行的最长允许时间。这在某些场景下尤为关键,例如,当当前事务所需的数据被另一个事务或代码锁定时,本事务可能需要等待并尝试加锁。 我们可以通过timeout属性
来设置超时限制,其单位为秒。设定超时属性后,为了验证其效果,我们可以在业务方法中插入线程休眠代码来进行模拟和测试
异常属性
异常属性指定了在事务中发生何种异常时应执行回滚操作,以及在哪些异常下应提交数据。我们可以通过属性rollbackFor
和noRollbackFor
来进行设置。
在Spring的事务管理中,异常属性的默认设置是
- 当事务中发生
RuntimeException
及其子类的异常时,系统会自动进行回滚 - 当事务中发生
Exception
及其子类的异常时,则默认执行提交操作。
对于大多数实际场景,建议沿用此默认值,尤其是对于RuntimeException及其子类
总结
经过上述详细的探讨,我们对Spring事务中的各项属性有了深入的了解。现在,我们来做一个简明扼要的总结:
- 隔离属性:推荐使用默认值。
- 传播属性:对于增删改操作,建议直接使用默认值,即REQUIRED。而对于查询操作,应手动设置为SUPPORTS。
- 只读属性:对于增删改操作,使用默认值,即false;对于查询操作,应手动设置为true。
- 超时属性:根据具体业务需求来决定,但默认值为-1。
- 异常属性:建议使用默认设
因此,总结如下:
- 对于增删改操作:
@Transaction
- 对于查询操作:
@Transaction(propagation=Propagation.SUPPORTS, readOnly=true)
相关文章:

Spring5应用之事务属性
作者简介:☕️大家好,我是Aomsir,一个爱折腾的开发者! 个人主页:Aomsir_Spring5应用专栏,Netty应用专栏,RPC应用专栏-CSDN博客 当前专栏:Spring5应用专栏_Aomsir的博客-CSDN博客 文章目录 参考文献前言事务…...

C# 搭建一个简单的WebApi项目23.10.10
一、创建Web API 1、创建一个新的web API项目 启动VS 2019,并在“开始页”选择“创建新项目”。或从“文件”菜单选择“新建”,然后选择“项目”。 选择ASP.NET Web应用程序(.NET Framework) 2.点击下一步,到这个页面时选择Web API。 3.选中…...

VGG卷积神经网络实现Cifar10图片分类-Pytorch实战
前言 当涉足深度学习,选择合适的框架是至关重要的一步。PyTorch作为三大主流框架之一,以其简单易用的特点,成为初学者们的首选。相比其他框架,PyTorch更像是一门易学的编程语言,让我们专注于实现项目的功能࿰…...

CentOS 7文件系统中的软链接和硬链接
软链接(Symbolic Link) 软链接,也称为符号链接,是一个指向另一个文件或目录的特殊类型的文件。它是一个指向目标文件的符号,就像快捷方式一样。软链接的创建和使用非常灵活,适用于各种情况。 创建软链接 …...

【AI】深度学习——前馈神经网络——全连接前馈神经网络
文章目录 1.1 全连接前馈神经网络1.1.1 符号说明超参数参数活性值 1.1.2 信息传播公式通用近似定理 1.1.3 神经网络与机器学习结合二分类问题多分类问题 1.1.4 参数学习矩阵求导链式法则更为高效的参数学习反向传播算法目标计算 ∂ z ( l ) ∂ w i j ( l ) \frac{\partial z^{…...

超简单的视频截取方法,迅速提取所需片段!
“视频可以截取吗?用相机拍摄了一段视频,但是中途相机发生了故障,录进去了很多不需要的片段,现在想截取一部分视频出来,但是不知道方法,想问问广大的网友,知不知道视频截取的方法。” 无论是工…...

ArcGIS/GeoScene脚本:基于粒子群优化的支持向量机回归模型
参数输入 1.样本数据必须包含需要回归的字段 2.回归字段是数值类型 3.影响因子是栅格数据,可添加多个 4.随机种子可以确保每次运行的训练集和测试集一致 5.训练集占比为0-1之间的小数 6.迭代次数:迭代次数越高精度越高,但是运行时间越长…...

vue3组件的通信方式
一、vue3组件通信方式 通信仓库地址:vue3_communication: 当前仓库为贾成豪老师使用组件通信案例 不管是vue2还是vue3,组件通信方式很重要,不管是项目还是面试都是经常用到的知识点。 比如:vue2组件通信方式 props:可以实现父子组件、子父组件、甚至兄弟组件通信 自定义事件:可…...

Qt QPair
QPair 文章目录 QPair 摘要QPairQPair 特点代码示例QPair 与 QMap 区别 关键字: Qt、 QPair、 QMap、 键值、 容器 摘要 今天在观摩小伙伴撸代码的时候,突然听到了QPair自己使用Qt开发这么就,竟然都不知道,所以趁没有被人发…...

K8S云计算系列-(3)
K8S Kubeadm案例实战 Kubeadm 是一个K8S部署工具,它提供了kubeadm init 以及 kubeadm join 这两个命令来快速创建kubernetes集群。 Kubeadm 通过执行必要的操作来启动和运行一个最小可用的集群。它故意被设计为只关心启动集群,而不是之前的节点准备工作…...

ardupilot罗盘数据计算航向
目录 文章目录 目录摘要1.数据特点2.数据结论1.结论2.结论摘要 本节主要记录ardupilot 根据罗盘数据计算航向的过程。 如果知道了一组罗盘数据,我们可以粗略估计航向:主要后面我们所说的X和Y都是表示的飞机里面的坐标系,也就是X前Y右边,如果按照罗盘坐标系Y实际在左边。 我…...

第六章:最新版零基础学习 PYTHON 教程—Python 正则表达式(第一节 - Python 正则表达式)
在本教程中,您将了解RegEx并了解各种正则表达式。 常用表达为什么使用正则表达式基本正则表达式更多正则表达式编译的正则表达式 目录 元字符 为什么是正则表达式?...

docker安装Jenkins完整教程
1.docker拉取 Jenkins镜像并启动容器 新版本的Jenkins依赖于JDK11 我们选择docker中jdk11版本的镜像 # 拉取镜像 docker pull jenkins/jenkins:2.346.3-2-lts-jdk11 2.宿主机上创建文件夹 # 创建Jenkins目录文件夹 mkdir -p /data/jenkins_home # 设置权限 chmod 777 -R /dat…...

[CISCN 2019初赛]Love Math - RCE(异或绕过)
[CISCN 2019初赛]Love Math 1 解题流程1.1 分析1.2 解题题目代码: <?php //听说你很喜欢数学,不知道你是否爱它胜过爱flag if(!isset($_GET[c]))...

C++ 使用getline()从文件中读取一行字符串
我们知道,getline() 方法定义在 istream 类中,而 fstream 和 ifstream 类继承自 istream 类,因此 fstream 和 ifstream 的类对象可以调用 getline() 成员方法。 当文件流对象调用 getline() 方法时,该方法的功能就变成了从指定文件中读取一行字符串。 该方法有以下 2 种语…...

JS进阶-原型
原型 原型就是一个对象,也称为原型对象 构造函数通过原型分配的函数是所有对象所共享的 JavaScript规定,每一个构造函数都有一个prototype属性,指向另一个对象,所以我们也称为原型对象 这个对象可以挂载函数,对象实…...

虹科方案 | 汽车CAN/LIN总线数据采集解决方案
全文导读:现代汽车配备了复杂的电子系统,CAN和LIN总线已成为这些系统之间实现通信的标准协议,为了开发和优化汽车的电子功能,汽车制造商和工程师需要可靠的数据采集解决方案。基于PCAN和PLIN设备,虹科提供了一种高效、…...

HTML5+CSSDAY4综合案例一--热词
样式展示图: 代码如下: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>热词…...

【源码】hamcrest 源码阅读 泛型 extends 和迭代器模式
文章目录 前言1. 泛型参数和自定义迭代器1.1 使用场景1.2 实现 2. 值得一提 前言 官方文档 Hamcrest Tutorial 上篇文章 Hamcrest 源码阅读及空对象模式、模板方法模式的应用 本篇文章 迭代器模式 1. 泛型参数和自定义迭代器 hamcrest 作为一个matcher库,把某个…...

IntelliJ IDEA 2023.1 版本可以安装了
Maven 的导入时间更加快了。 收到的有邮件提醒安装。 安装后的版本,其实就是升级下,并没有什么主要改变。 IntelliJ IDEA 2023.1 版本可以安装了 - 软件技术 - OSSEZMaven 的导入时间更加快了。 收到的有邮件提醒安装。 安装后的版本,其实就是…...

安全论坛和外包平台汇总
文章目录 一. 网络安全论坛汇总二. 外包平台汇总1. 国内:2. 国外 一. 网络安全论坛汇总 安全焦点BugTraq:http://www.fuzzysecurity.com/Exploit-DB:https://www.exploit-db.com/hackone:https://www.hackerone.com/FreeBuf&…...

9-2-Dataset创建-import调用
文章目录 utils_dataset.pymain-调用utils_dateset.pyutils_dataset.py 1默认:没有改变尺寸,数据集中的图像可以是任意形状尺寸。dataloader中必须令batch_size=1 transforms.Resize((宽,高))(image) 和 batch_size=1 必须用其一 原因:当batch_size>1时,每个batch的数…...

XSS原理
原理: 这是一种将任意 Javascript 代码插入到其他Web用户页面里执行以达到攻击目的的漏洞。攻击者利用浏览器的动态展示数据功能,在HTML页面里嵌入恶意代码。当用户浏览改页时,这些潜入在HTML中的恶意代码会被执行,用户浏览器被攻…...

记一个带批注、表头样式的导入导出excel方法(基于easyexcel)
技术栈:easyexcel-2.2.10,poi-4.1.2,lombok,hutool-5.8.19;公司自用导入导出方法,可能不是那么的优雅,但胜在稳定实用。 /*** Author 955* Date 2023-10-10 11:52* Description 错误批注信息对…...

二叉搜索树--新增节点-力扣 701 题
例题细节二叉搜索树的基础操作-CSDN博客也讲过了(put),下面给出递归实现 public TreeNode insertIntoBST(TreeNode node, int val) {//找到空位了if(node null) {return new TreeNode(val);}if(val < node.val) {//一直找到有null的位置…...

C++ - 智能指针 - auto_ptr - unique_ptr - std::shared_ptr - weak_ptr
前言 C当中的内存管理机制需要我们自己来进行控制,比如 在堆上 new 了一块空间,那么当这块空间不需要再使用的时候。我们需要手动 delete 掉这块空间,我们不可能每一次都会记得,而且在很大的项目程序当中,造成内存泄漏…...

【快速入门】JVM之类加载机制与Native
感慨: 如何定义一个合格的Java程序员,Java程序员要了解掌握哪些知识点,网上的面试题太多了,后端需要了解掌握的知识点太多太多了,Java基础、数据结构、异常、多线程、Spring、Spring boot、事务、算法、数据库…...

R实现数据分布特征的视觉化——多笔数据之间的比较
大家好,我是带我去滑雪! 如果要对两笔数据或者多笔数据的分布情况进行比较,Q-Q图、柱状图、星形图都是非常好的选择,下面开始实战。 (1)绘制Q-Q图 首先导入数据bankwage.csv文件,该数据集…...

TCPUDP
TCP 1.什么是TCP TCP是处于运输层的通信协议,该协议能够实现数据的可靠性传输。 2.TCP报文格式 源端口和目的端口:各占两个字节,发送进程的端口和接收进程的端口号。 序号:占4个字节,序号如果增加到溢出,则下一个序…...

设计模式 - 备忘录模式
目录 一. 前言 二. 实现 三. 优缺点 一. 前言 备忘录模式又称快照模式,是一种行为型设计模式。它可以在不破坏封装性的前提下捕获一个对象的内部状态,并在对象之外保存这个状态,以便在需要的时候恢复到原先保存的状态。在不违反封装的情况…...