Spring 事务是什么 ?事务的传播机制?

news2025/1/18 3:17:52

目录

1. 什么是事务?

1. Spring 事务三大基础设施

1.1 PlatformTransactionManager 平台事务管理器

1.2 TransactionDefinition 事务属性定义

1.3 TransactionStatus 事务状态

3. Transaction 注解

4. Spring 事务角色

5. @Transaction 注解属性

5.1 事务的回滚规则

5.2 事务的传播行为


1. 什么是事务?

了解过 MySQL 事务的同学应该都知道,事务通常是由多个 SQL 语句共同构成的一组逻辑操作单元,要么同成功,要么同失败。而我们的 Spring 事务也是一样的道理,它可以保证数据层或业务层的一系列操作要么同时成功,要么同时失败。其底层只是对 MySQL 的事务做了封装,因此如果你明白数据库的事务,了解 Spring 事务也是轻而易举。

1. Spring 事务三大基础设施

在 Spring 框架中,它给我们提供了三个和事务有关的最基础也最重要的三个接口或类。它们是 PlatformTransactionManager,TransactionDefinition,TransactionStatus。下面我来逐个说一下它们的作用。

1.1 PlatformTransactionManager 平台事务管理器

平台事务管理器 PlatformTransactionManager 是一个接口,里面定义了三个最基本的方法,它从上层规范了子类的行为,具体的代码实现交给了各个不同的平台。

这一点类似于我们之前所学习过的 JDBC ,sun 公司制定了一套数据库接口标准,各大数据库厂商去实现这些接口的方法,我们程序员不需要关心各个数据库厂商的具体实现。我们所熟知使用的 DatasourceTransactionManager 就是该接口的其中一个实现类。

它的源码我截取出来如下:

public interface PlatformTransactionManager extends TransactionManager {
    TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;
// 提交事务方法
    void commit(TransactionStatus var1) throws TransactionException;
// 回滚事务方法
    void rollback(TransactionStatus var1) throws TransactionException;
}

1.2 TransactionDefinition 事务属性定义

这个接口中定义了很多的属性,它更多是用来描述事务的具体规则,主要是 事务的隔离性,传播性,回滚规则,超时时间,事务是否只读。

我截取了该接口的源码如下

getIsolationLevel() 获取事务的隔离级别,如数据库的读未提交,读已提交,可重复读,序列化四种隔离级别;

getPropagationBehavior() 获取事务的传播行为,后面我会专门说到它,也是面试中会问到的点,这里先混个眼熟;

getTimeout() 获取事务的超时时间;

isReadOnly() 是否为只读;

1.3 TransactionStatus 事务状态

public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {
// 判断是否有保存点,类似于我们数据库中的事务保存点,回滚事务可以让其回滚至该点
    boolean hasSavepoint();
// 该方法可以把底层的方法刷新到数据库中去,现在用的不太多了
    void flush();
}

3. Transaction 注解

Spring 为我们提供了注解的方式开启事务,传统的编程式事务由于事务代码与业务代码糅合在一起,导致项目耦合度过高,因此在 Spring Boot 项目中,我们通常可以利用注解开启事务。

而且,@Transactions 注解不仅可以加在类上,也可以加在接口上,@Transaction 注解加载业务层实现类上,表示开启当前方法的事务,为了降低耦合度,我建议各位同学在业务层接口对各个接口也做 @Transactions 事务标记,标记当前接口中的所有方法是事务。

如果标注在接口上,表示该接口中的所有抽象方法都是事务,如下所示;

@Transactional
public interface UserService {
    
    User queryById(Long id);
    
    boolean transMoney();

}

如果标注在类上,表示该类中所有的方法都是事务,如下接口实现类;

@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    public User queryById(Long id) {
        return userMapper.findById(id);
    }
    
    @Override
    public boolean transMoney() {
        userMapper.outMoney();
        userMapper.inMoney();
        return true;
    }
}

如果标注在方法上,表示当前方法是一个事务,如下代码;

@Override
    @Transactional
    public boolean transMoney() {
        userMapper.outMoney();
        userMapper.inMoney();
        return true;
    }

4. Spring 事务角色

Spring 事务中的角色分为事务管理员与事务协调员。

如下图

我们现在定义了一个两个接口转账接口。原本,我们的 outMoney 和 inMoney 分别是两个事务,互不相关。

然后定义一个转账业务方法,调用两个转账接口。我们在业务方法上加上@Transaction注解,表示开启 Spring 事务,这又是一个新的事务。

一旦我们开启了 Spring 事务,那么原本的 outMoney 和 inMoney 这两个事务就会加入到我的Spring 事务中,这样一来,三个事务就变成了一个事务,当我们的业务层中 tansfer 方法出现了错误,它就会回滚。就可以做到所有的操作同成功同失败的效果。

事务管理员:发起事务方,在 Spring 中通常指代业务层开启事务的方法。

事务协调员:加入事务方,在 Spring 中通常指代数据层方法,也可以是业务方法。

5. @Transaction 注解属性

我们在使用 @Transaction 这个注解的时候,可以为其配置很多属性

这里我们需要重点掌握的是 rollbackFor(回滚规则) 和 propagation(传播行为) 。

5.1 事务的回滚规则

我们通常所熟知的,在事务中,一旦发生异常,就要进行回滚。但是在 Spring 事务中,有一些异常它是不会回滚的,所以就需要我们手动设置。

在 Spring 事务中,只有遇到 Error 错误和 RuntimeException 运行时异常才会发生回滚,其余的异常即便发生事务也不会进行回滚。

例如在事务中如果发生了 IOException,它就不会回滚事务。如下图所示,

我们在两个转账操作之间加上 IOException,执行该方法,那么之际情况就是 outMoney 方法正常执行不会滚,inMoney 方法因为抛出异常不会运行。

想要解决此问题,我们就需要在 @Transaction 注解中配置 rollbackFor 属性,指定碰到哪些异常时回滚,如下图所示,我们直接将属性配置在接口上,降低耦合度

配置完成之后,此时该事务再遇到 IOException,就会回滚事务。


5.2 事务的传播行为

事务传播行为,我们也可以把它理解为 事务协调者对事务管理者的态度,什么意思呢?

刚才我说到,Spring 开启事务之后,所有的事务都会加入到Spring 开启的这个事务,使所有事务成为一个事务达到同成功同失败的目的。

我来举个例子,刚才的转账案例,我加入一个功能,不管转账是否成功,都需要在数据库中进行记录,说白了就是添加一个功能。

做法:正常情况下,我们需要建立数据库转账记录表——>Java中创建转账日志实体类——>编写数据访问层接口——>编写业务方法。然后将该业务方法也作为事务加入到 转账事务中就可以了。

但各位仔细看,不管转账是否成功,都需要在数据库进行记录,那么现在就出现问题了,如果我们按照原来的 Spring 事务操作是有问题的。如果转账事务成功,数据库日志会记录。如果转账事务不成功,事务回滚,数据库的日志表中还会有记录吗?日志是肯定也不会存在数据库中,如此一来,就无法达到我们的目的。

此时,就需要用到事务的传播行为这一属性,它需要在 @Transaction 这一注解中进行属性配置的。还是和刚才一样,我们在方法的接口上配置@Transaction(propagation = REQUIRES_NEW)。

所有传播行为如下表所示

可以看到,REQUIRES_NEW 中事务协调员在事务管理员有事务的情况下,它又单独开辟了一个事务,这样一来,我们的转账日志记录功能就与转账功能本身分割开了,成了两个事务,那么转账日志记录这个事务就不会随着转账事务的回滚而回滚,不管是否成功,都会进行记录,这样就得到了我们的目的。

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

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

相关文章

WebGPU加载Wavefront .OBJ模型文件

在开发布料模拟之前,我想使用 WebGPU 开发强大的代码基础。 这就是为什么我想从 Wavefront .OBJ 文件加载器开始渲染 3D 模型。 这样,我们可以快速渲染 3D 模型,并构建一个简单而强大的渲染引擎来完成此任务。 一旦我们有了扎实的基础&#x…

山西电力市场日前价格预测【2023-08-30】

日前价格预测 预测明日(2023-08-30)山西电力市场全天平均日前电价为317.95元/MWh。其中,最高日前电价为373.07元/MWh,预计出现在19: 45。最低日前电价为248.17元/MWh,预计出现在13: 30。 价差方向预测 1: 实…

手机云控设计思路

本系统为任务分发系统,上游发布任务或者接受其他平台系统分发的任务,对任务进行规则引擎处理后分类,由核心分发系统部分进行对存活的空闲终端进行分发任务,终端做完任务后进行反馈给任务系统. 核心要处理的点是终端存活与空闲的统计、任务平均分布下发给终端的算法,保证分布的…

RK3562 VS A40i 性能对比

RK3562作为瑞芯微新推出的低功耗、高性价比的通用SOC,在智能商显和工业控制领域又为深圳触觉智能增加了一款强有力的高性价比产品。RK3562是一款专为智能显示设备设计的高性能、低功耗四核应用处理器,其工规版本RK3562J还具备CAN FD接口,工作…

基于SSM的旅游管理系统jsp房源信息java源代码Mysql

本项目为前几天收费帮学妹做的一个项目,Java EE JSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。 一、项目描述 基于SSM的旅游管理系统 系统有2权限:管理…

创作与合作:AI绘画API与艺术家的共舞

引言 在数字时代,技术和艺术之间的界限正在变得越来越模糊。人工智能(AI)绘画API是一个典型的例子,它已经开始改变我们对创作和艺术的理解方式。然而,与传统艺术手法相比,AI绘画API并不是要取代艺术家&…

JavaScript原型链污染

前言 在浏览某个论坛的时候,第一次看到了JavaScript原型链污染漏洞。当时非常的好奇,当时我一直以为js作为一种前端语言,就算存在漏洞也是针对前端,不会危害到后端,因此我以为这种漏洞危害应该不大。可当我看到他的漏…

Feign在进行序列化时遇到泛型类型的擦除,导致反序列化时成了LinkedHashMap

Feign在进行序列化时遇到泛型类型的擦除,导致反序列化时成了LinkedHashMap 故障背景问题分析修复方案修复方案一 避免使用泛型修复方案二 解析data泛型的时候处理 故障背景 假设我们有一个Feign接口 import org.springframework.cloud.openfeign.FeignClient; imp…

深度学习卷积神经网络识别光学字符验证码,及captcha使用简单案例

深度学习卷积神经网络识别验证码 文章目录 深度学习卷积神经网络识别验证码一、引言二、导入必要的库三、防止 tensorflow 占用所有显存四、定义数据生成器并测试五、定义网络结构六、训练模型七、测试模型 一、引言 验证码识别,本身使用来判断访问网站的用户是不是…

更新netframe报错,更新.netFrame 到4.8

背景: 更新了Java程序后,启动提示我更新netframe 手动更新.netFrame 到4.8 ndp48-x86-x64-allos-enu.exe 发现报错: 继续百度解决报错。方案为: https://blog.csdn.net/i2blue/article/details/88821583 产生阻滞的问题: 你…

快手Java一面,全是基础

现在已经到了面试招聘比较火热的时候,准备面试的过程中,一定要多看面经,多自测! 今天分享的是一位贵州大学的同学分享的快手一面面经。 快手一面主要会问一些基础问题,也就是比较简单且容易准备的常规八股&#xff0…

零代码,使用 Dify 和 Laf 两分钟接入企业微信 AI 机器人

Dify 允许创建 AI 应用,并提供二次开发的能力。这里我将演示创建一个法律问答助手的 AI 应用,称作“知法”。在本篇教程中,我将指导你为“知法”接入企业微信。 前置准备 企业微信的管理员权限一个 Dify 的帐号一个 Laf 云的帐号&#xff0…

【Linux】序列化与反序列化

目录 前言 什么是应用层? 再谈"协议" 什么是序列化和反序列化 网络版计算器 整体流程实现 Sock.hpp的实现 TcpServer.hpp的实现 Protocol.hpp的实现 CalServer.cc的编写 CalClient.cc的编写 整体代码 前言 本章是属于TCP/UDP四层模型中的第一层…

opencv的使用(Ubuntu linux环境,AS jni,AS java)

最近要完成一个功能,就是把四个视频合成左右上下分布的一个视频。尝试很多方法,最终使用opencv来实现该功能。(通过opencv实现的视频好像没有声音。)研究的步骤,首先在Ubuntu环境测试,该功能是否实现。然后…

13.搬砖

目录 题目 Description Input Output 思路(归并排序) 具体步骤如下 C整体代码(含详细注释) 归并排序总结 核心步骤 代码模板 题目 Description 小张在暑假时间来到工地搬砖挣钱。包工头交给他一项艰巨的任务&#xff0…

Mavan进阶之父子模块(继承)

文章目录 Mavan 父子模块(继承)1. 父项目2. 子项目3. 父子项目的使用 Mavan 父子模块(继承) 「继承」是 Maven 中很强大的一种功能,继承可以使得子 pom 可以获得 parent 中的各项配置,可以对子 pom 进行统…

深度学习之反卷积

具体推理可以参考https://blog.csdn.net/zhsmkxy/article/details/107073350

uniapp微信小程序使用stomp.js实现STOMP传输协议的实时聊天

简介: 原生微信小程序中使用 本来使用websocket,后端同事使用了stomp协议,导致前端也需要对应修改。 如何使用 1.yarn add stompjs 2.版本 “stompjs”: “^2.3.3” 3.在static/js中新建stomp.js和websocket.js,然后在需要使用…

一文讲透超宽带(UWB)前世今生

►►►UWB大火与巨头入局 传闻已久的蔚来手机可能即将要发布了。据工信部官网显示:申请单位为蔚来移动科技有限公司、型号为N2301的手机已正式完成入网。相关认证信息显示,N2301支持UWB,可以被用作蔚来汽车的数字钥匙。 图 1 蔚来手机概念图 …

第十四课 定语从句

文章目录 前言 所有定语从句的连接词是没有意思的一、定语从句的定义和结构二、关系代词引导的定语从句1、whowho谓语(宾语)状语who系动词表语状语who助动词及物动词的过去分词 2、whomwhom主语及物动词(状语)whom主语谓语to及物动…