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

目录

1. 什么是事务?

2. Spring 事务三大基础设施

2.1 PlatformTransactionManager 平台事务管理器

2.2 TransactionDefinition 事务属性定义

2.3 TransactionStatus 事务状态

3. Transaction 注解

4. Spring 事务角色

5. @Transaction 注解属性

5.1 事务的回滚规则

5.2 事务的传播行为


1. 什么是事务?

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

2. Spring 事务三大基础设施

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

2.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;
}

2.2 TransactionDefinition 事务属性定义

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

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

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

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

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

isReadOnly() 是否为只读;

2.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 {@Autowiredprivate UserMapper userMapper;public User queryById(Long id) {return userMapper.findById(id);}@Overridepublic boolean transMoney() {userMapper.outMoney();userMapper.inMoney();return true;}
}

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

@Override@Transactionalpublic 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.hqwc.cn/news/93767.html

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

相关文章

HTTP与SOCKS5的区别对比

在互联网世界中,服务器是一种重要的工具,可以帮助我们提高网络安全性等。今天,我们将重点关注两种常见的技术:HTTP和SOCKS5。让我们深入了解它们的工作原理、用途和优缺点,并通过Python代码示例学习如何使用它们。 HT…

Kubernetes(K8s)基本环境部署

此处只做学习使用,配置单master环境。 一、环境准备 1、ip主机规划(准备五台新机)>修改各个节点的主机名 注意:关闭防火墙与selinux 节点主机名ip身份joshua1 kubernetes-master.openlab.cn 192.168.134.151masterjoshua2k…

ChatGPT 总结前端HTML, JS, Echarts都包含哪些内容

AIGC ChatGPT ,BI商业智能, 可视化Tableau, PowerBI, FineReport, 数据库Mysql Oracle, Office, Python ,ETL Excel 2021 实操,函数,图表,大屏可视化 案例实战 http://t.csdn.cn/zBytu

css让元素保持等比例宽高

使用新属性 aspect-ratio: 16/9; 代码示例 <style>div {width: 60%;/* 等比例宽高 */aspect-ratio: 16/9;background-color: red;margin: auto;}</style> </head><body><div></div> </body>示例 aspect-ratio兼容性

使用正则表达式在中英文之间添加空格

有时为了排版需要&#xff0c;我们可能需要在文章的中英文之间添加空格&#xff0c;特别是中文中引用了英文单词时&#xff0c;这种情况使用正则表达式整体修订是最明智的做法。首先&#xff0c;推荐使用在线的正则表格式工具&#xff1a;https://regex101.com/ , 该工具非常强…

Selenium-用这个框架自动化任何你想做的事情!

Chrome DevTools 简介 Chrome DevTools 是一组直接内置在基于 Chromium 的浏览器&#xff08;如 Chrome、Opera 和 Microsoft Edge&#xff09;中的工具&#xff0c;用于帮助开发人员调试和研究网站。 借助 Chrome DevTools&#xff0c;开发人员可以更深入地访问网站&#xf…

nginx反向代理 负载均衡

目录 1.反向代理介绍&#xff1a; 2.七层代理和四层代理&#xff1a; 2.1 七层代理&#xff1a; 2.2 四层代理&#xff1a; 3.反向代理web服务器&#xff1a; 3.1 代理服务器配置&#xff1a; 3.2 服务器配置 &#xff1a; 3.3 客户端访问&#xff1a; 3.4 代理不同端口&am…

Lvs+KeepAlived高可用高性能负载均衡

目录 1.环境介绍 2.配置keepalived 3.测试 1.测试负载均衡 2.测试RS高可用 3.测试LVS高可用 3.1测试lvs主服务宕机 3.2.测试lvs主服务器恢复 4.我在实验中遇到的错误 1.环境介绍 环境&#xff1a;centos7 RS1---RIP1:192.168.163.145 VIP 192.168.163.200 RS2---RIP2…

Java智慧工地源码 智慧工地APP源码

Java智慧工地源码 智慧工地APP源码 系统定义&#xff1a; 智慧工地信息化管理平台是依托计算机信息、网络通讯、物联网、系统集成及云计算技术&#xff0c;通过数据采集、信息动态交互、智能分析&#xff0c;建立起来的一套集成的项目建设综合管理系统。实现项目管理信息化、网…

wangluobiancheng

UDP send: receive: TCP

ARM DIY(四)WiFi 调试

文章目录 焊接打开内核编译选项重新编译内核烧录 && 运行 && 测试完善脚本测速手搓天线正式天线 焊接 换个粗点的风枪嘴&#xff0c;让热风覆盖 RTL8823BS 整体模块&#xff0c;最终实现自动归位 焊接 SDIO 接口的上拉电阻以及复位引脚上拉电阻 硬件部分就这…

C# Dapper 操作Oracle数据库

nuget安装内容 1.配置连接字符串 OracleConnectionString这个可用 {"Logging": {"LogLevel": {"Default": "Information","Microsoft.AspNetCore": "Warning"}},"AllowedHosts": "*","…