Spring事务管理

目录

1.什么是事务

事务的四大特性(ACID)

2.Spring中的事务

2.1PlatformTransactionManager

2.2TransactionDefinition

2.3TransactionStatus

3.编程式事务

4.声明式事务(@Transactional)

5. 事务属性

5.1 隔离性(isolation)

5.2 传播性(propagation)

REQUIRED

REQUIRES_NEW

NESTED

5.3 回滚规则(rollbackFor)

5.4 是否只读(readOnly)

5.5 超时时间(timeout)

6.Spring事务的失效场景


1.什么是事务

数据库事务是指作为单个逻辑工作单元执行的一系列操作,这些操作要么一起成功,要么一起失败,是一个不可分割的工作单元。

涉及到事务的场景非常多,一个 service 中往往需要调用不同的 dao 层方法,这些方法要么同时成功要么同时失败,我们需要在 service 层确保这一点。

事务的四大特性(ACID)

  • 原子性(Atomicity): 一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。即,事务不可分割、不可约简。

  • 一致性(Consistency): 在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设约束、触发器、级联回滚等。

  • 隔离性(Isolation): 数据库允许多个并发事务同时对其数据进行读写和修改,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括未提交读(Read Uncommitted)、提交读(Read Committed)、可重复读(Repeatable Read)和串行化(Serializable)。

  • 持久性(Durability): 事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

2.Spring中的事务

Spring 中对事务的支持提供了三大核心接口,我们先来了解下。

  1. PlatformTransactionManager
  2. TransactionDefinition
  3. TransactionStatus

2.1PlatformTransactionManager

PlatformTransactionManager 中定义了基本的事务操作方法,这些事务操作方法的具体实现都是由不同的子类来实现的。相当于 PlatformTransactionManager 是定义了一套标准,我们不需要掌握具体实现类的用法,只需要掌握好 PlatformTransactionManager 的用法即可。

public interface PlatformTransactionManager {TransactionStatus getTransaction(@Nullable TransactionDefinition definition);void commit(TransactionStatus status) throws TransactionException;void rollback(TransactionStatus status) throws TransactionException;
}

PlatformTransactionManager 中主要有如下三个方法:

1.getTransaction()

getTransaction() 是根据传入的 TransactionDefinition 获取一个事务对象,TransactionDefinition 中定义了一些事务的基本规则,例如传播性、隔离级别等。

2.commit()

commit() 方法用来提交事务。

3.rollback()

rollback() 方法用来回滚事务。

2.2TransactionDefinition

TransactionDefinition 用来描述事务的具体规则,也称作事务的属性。

事务主要有五种属性:

  1. 隔离性
  2. 传播性
  3. 回滚规则
  4. 超时时间
  5. 是否只读

TransactionDefinition 接口 中还有5个对应的方法:

  1. getIsolationLevel(),获取事务的隔离级别
  2. getName(),获取事务的名称
  3. getPropagationBehavior(),获取事务的传播性
  4. getTimeout(),获取事务的超时时间
  5. isReadOnly(),获取事务是否是只读事务

如果开发者使用了编程式事务的话,直接使用 DefaultTransactionDefinition 即可。

2.3TransactionStatus

TransactionStatus表示一个事物的状态。接口提供了控制事务执行和查询事务状态的方法。比如当前调用栈中之前已经存在了一个事物,那么就是通过该接口来判断的,TransactionStatus接口可以让事务管理器控制事务的执行,比如检查事务是否为一个新事务,或者是否只读,TransactionStatus还可以初始化回滚操作。

接口继承了SavepointManager接口,因此封装了事物中回滚点的相关操作

SavepointManager接口:

public interface SavepointManager {//1.创建回滚点Object createSavepoint() throws TransactionException;//2.回滚到回滚点 void rollbackToSavepoint(Object savepoint) throws TransactionException;//3.释放回滚点void releaseSavepoint(Object savepoint) throws TransactionException;
}

TransactionStatus接口:

public interface TransactionStatus extends SavepointManager, Flushable {//是否是一个新的事物boolean isNewTransaction();//判断是否有回滚点boolean hasSavepoint();//将一个事务标识为不可提交的。在调用完setRollbackOnly()后只能被回滚//在大多数情况下,事务管理器会检测到这一点,在它发现事务要提交时会立刻结束事务。//调用完setRollbackOnly()后,数数据库可以继续执行select,但不允许执行update语句,因为事务只可以进行读取操作,任何修改都不会被提交。void setRollbackOnly();boolean isRollbackOnly();@Overridevoid flush();//判断事物是否已经完成boolean isCompleted();
}

3.编程式事务

编程式事务是指将事务管理代码嵌入嵌入到业务代码中,来控制事务的提交和回滚。通过 PlatformTransactionManager 或者 TransactionTemplate 可以实现编程式事务。如果是在 Spring Boot 项目中,这两个对象 Spring Boot 会自动提供,我们直接使用即可。

使用 TransactionTemplate 来管理事务:

@Autowired
private TransactionTemplate transactionTemplate;
public void testTransaction() {transactionTemplate.execute(new TransactionCallbackWithoutResult() {@Overrideprotected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {try {// ....  业务代码} catch (Exception e){//回滚transactionStatus.setRollbackOnly();}}});
}

使用 TransactionManager 来管理事务:

@Autowired
private PlatformTransactionManager transactionManager;public void testTransaction() {TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());try {// ....  业务代码transactionManager.commit(status);} catch (Exception e) {transactionManager.rollback(status);}
}

编程式事务由于代码入侵太严重了,因为在实际开发中使用的很少,我们在项目中更多的是使用声明式事务

4.声明式事务(@Transactional)

声明式事务将事务管理代码从业务方法中抽离了出来,利用到了 Spring 当中的AOP,以声明式的方式来实现事务管理,对于开发者来说,声明式事务显然比编程式事务更易用、更好用。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,执行完目标方法之后根据执行的情况提交或者回滚。

声明式事务虽然优于编程式事务,但也有不足,声明式事务管理的粒度是方法级别,而编程式事务是可以精确到代码块级别的。

5. 事务属性

5.1 隔离性(isolation)

高性能MySQL读书笔记第一章——MySQL架构_汤姆&Tom的博客-CSDN博客

5.2 传播性(propagation)

事务传播行为是为了解决业务层方法之间互相调用的事务问题,当一个事务方法被另一个事务方法调用时,事务该以何种状态存在?例如新方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行,等等,这些规则就涉及到事务的传播性。

关于事务的传播性,Spring 主要定义了如下几种:

传播性描述
REQUIRED(默认)如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务
SUPPORTS如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行
MANDATORY如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常
REQUIRES_NEW创建一个新的事务,如果当前存在事务,则把当前事务挂起
NOT_SUPPORTED以非事务方式运行,如果当前存在事务,则把当前事务挂起
NEVER以非事务方式运行,如果当前存在事务,则抛出异常
NESTED如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 TransactionDefinition.PROPAGATION_REQUIRED

这里只讲解部分传播性,最重要的还是默认的 REQUIRED

REQUIRED

这也是 @Transactional 默认的事务传播行为,指的是如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。更确切地意思是:

  • 如果外部方法没有开启事务的话,Propagation.REQUIRED 修饰的内部方法会开启自己的事务,且开启的事务相互独立,互不干扰。
  • 如果外部方法开启事务并且是 Propagation.REQUIRED 的话,所有 Propagation.REQUIRED 修饰的内部方法和外部方法均属于同一事务 ,只要一个方法回滚,整个事务都需要回滚。

REQUIRES_NEW

创建一个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部方法是否开启事务,Propagation.REQUIRES_NEW 修饰的内部方法都会开启自己的事务,且开启的事务与外部的事务相互独立,互不干扰。

  • 当类A中的 a 方法用默认 Propagation.REQUIRED模式,类B中的 b方法加上采用 Propagation.REQUIRES_NEW模式,然后在 a 方法中调用 b方法操作数据库,然而 a方法抛出异常后,b方法并没有进行回滚,因为Propagation.REQUIRES_NEW会暂停 a方法的事务

总结就是a不影响b,b影响a(如果catch了异常则不影响a)

NESTED

如果当前存在事务,就在当前事务内执行;否则开启自己的事务

  • 当类A中的 a 方法用默认 Propagation.REQUIRED模式,类B中的 b方法加上采用 Propagation.NESTED模式,然后在 在a 方法里调用 b方法操作数据库,然而 b方法抛出异常后,a方法是不的回滚

总结就是 a影响b,b可能影响 a (如果不处理异常)

5.3 回滚规则(rollbackFor)

默认情况下,事务只有遇到 运行期异常(RuntimeException 的子类)以及 Error 时才会回滚,在遇到 检查型(Checked Exception)即 IOException 异常时不会回滚。

@Transactional(rollbackFor = IOException.class)

5.4 是否只读(readOnly)

只读事务一般设置在查询方法上,但不是所有的查询方法都需要只读事务,要看具体情况。

一般来说,如果这个业务方法只有一个查询 SQL,那么就没必要添加事务,强行添加最终效果适得其反。

但是如果一个业务方法中有多个查询 SQL,情况就不一样了:多个查询 SQL,默认情况下,每个查询 SQL 都会开启一个独立的事务,这样,如果有并发操作修改了数据,那么多个查询 SQL 就会查到不一样的数据。此时,如果我们开启事务,并设置为只读事务,那么多个查询 SQL 将被置于同一个事务中,多条相同的 SQL 在该事务中执行将会获取到相同的查询结果。

@Transactional(readOnly = true)

5.5 超时时间(timeout)

超时时间是说一个事务允许执行的最长时间(单位为秒),如果超过该时间限制但事务还没有完成,则自动回滚事务。

@Transactional(timeout = 10)

6.Spring事务的失效场景

1.事务只能应用到 public 方法上才会有效。

2.事务需要从外部调用,Spring 自调事务(同一个类中)用会失效。即在同一个类里边,A 方法没有事务,B 方法有事务,A 方法调用 B 方法,则 B 方法的事务会失效,这点尤其要注意,因为代理模式只拦截通过代理传入的外部方法调用,所以自调用事务是不生效的

如下面,test方法调用 transfer 方法,出现异常后事务是不会回滚的。

@Service
public class UserService {@Autowiredprivate JdbcTemplate jdbcTemplate;@Transactionalpublic void transfer(){jdbcTemplate.update("update user set money = ? where username = ?;",1,"zhangsan");int i=1/0;}public void test(){//事务失效transfer();}
}

因为事务需要从外部调用,从外部注入UserService,直接调用transfer()方法 才可以。如下:

@RestController
public class Controller {@Autowiredprivate UserService userService;@GetMapping("/test")public void test(){userService.transfer();}
}

3.建议事务注解 @Transactional 一般添加在实现类上,而不要定义在接口上。如果加在接口类或接口方法上时,只有配置基于接口的代理这个注解才会生效。

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

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

相关文章

Linux-GPIO 配置pull up、pull down、no pull

author daisy.skye的博客_CSDN博客-Qt,嵌入式,Linux领域博主 https://blog.csdn.net/qq_40715266?typeblog 系列基于RK3568的Linux驱动开发——GPIO知识点(一)_daisy.skye的博客-CSDN博客基于RK3568的Linux驱动开发—— GPIO知识点(二&#…

【VisualGLM】大模型之 VisualGLM 部署

目录 1. VisualGLM 效果展示 2. VisualGLM 介绍 3. VisualGLM 部署 1. VisualGLM 效果展示 VisualGLM 问答 原始图片 2. VisualGLM 介绍 VisualGLM 主要做的是通过图像生成文字,而 Stable Diffusion 是通过文字生成图像。 一种方法是将图像当作一种特殊的语言进…

C语言刷题------(2)

C语言刷题——————(2) 刷题网站:题库 - 蓝桥云课 (lanqiao.cn) First Question:时间显示 题目描述 小蓝要和朋友合作开发一个时间显示的网站。 在服务器上,朋友已经获取了当前的时间,用一个整数表…

Nginx与docker配置安装

目录: Nginx的安装配置: 1、安装依赖包: 2、下载Nginx安装包: 3、解压Nginx压缩包: 4、配置Nginx编译环境: 5、编译并安装Nginx: 6、安装完Nginx后,可以切换到Nginx的安装目录…

python版《羊了个羊》游戏开发第一天

Python小型项目实战教学课《羊了个羊》 一、项目开发大纲(初级) 版本1.0:基本开发 课次 内容 技术 第一天 基本游戏地图数据 面向过程 第二天 鼠标点击和移动 面向对象 第三天 消除 设计模式:单例模式 第四天 完整…

clion使用qDebug()控制台无输出的可能解决方法

给项目添加一个环境变量 QT_ASSUME_STDERR_HAS_CONSOLE1参考网址:https://youtrack.jetbrains.com/issue/CPP-24369/Auto-enable-qDebug-console.log-output-to-the-debug-console-for-Qt-projects-on-Windows

Flutter:文件读取—— video_player、chewie、image_picker、file_picker

前言 简单学习一下几个比较好用的文件读取库 video_player 简介 用于视频播放 官方文档 https://pub-web.flutter-io.cn/packages/video_player 安装 flutter pub add video_player加载网络视频 class _MyHomePageState extends State<MyHomePage> {// 控制器late…

Android 开发者选项日志存储路径

android开发者选项中存在两个item是关于系统日志的。 1.日志记录器缓冲区大小 2.在设备上永久存储日志记录器数据 一个是用来设置缓冲区大小&#xff0c;一个是用来日志存储开关及过滤。 通过分析 system/core/logcat/logcatd.rc mkdir /data/misc/logd 0770 logd log 日志的…

ArcGIS Pro基础:【划分】工具实现等比例、等面积、等宽度划分图形操作

本次介绍【划分】工具的使用&#xff0c;如下所示&#xff0c;为该工具所处位置。使用该工具可以实现对某个图斑的等比例面积划分、相等面积划分和相等宽度划分。 【等比例面积】&#xff1a;其操作如下所示&#xff0c;其中&#xff1a; 1表示先选中待处理的图斑&#xff0c;2…

华为智选首款纯电轿跑“LUXEED”能大卖吗?

监制 | 何玺 排版 | 叶媛 华为智选纯电轿跑来袭&#xff01; 8月7日&#xff0c;华为常务董事余承东在社交媒体上发文&#xff0c;宣布华为智选即将推出首款“突破想象”的纯电轿跑车。 01 华为智选首款纯电轿跑来袭 余承东的发文引起了极大关注&#xff0c;在各大媒体的报…

动力节点Redis7实战教程,从基础到底层一套通关

Redis是一种非常强大的数据缓存和存储系统&#xff0c;既可以用作关系型数据库的缓存降低查询延迟&#xff0c;也可以作为一个分布式系统的共享数据存储。 动力节点的Redis7课程将带领大家完整的学习Redis7.0版本&#xff0c;内容涵盖Redis全套知识体系&#xff0c;由浅入深 总…

微信小程序读取本地json

首先在项目录下新建【server】文件夹&#xff0c;新建data.js文件&#xff0c;并定义好json数据格式。如下&#xff1a; pages/index/index.ts导入data.js并请求json pages/index/index.wxml页面展示数据

JavaWeb-能制作中小型网站企业管理系统(适合快速梳理)

导言 第一章 Web前端开发 一、初始web前端 二、HTML、CSS介绍 三、VsCode安装 四、标签 1 实现标题--排版 2 实现标题--样式 颜色表示 CSS选择器 3 实现标题--超链接 4 实现标签--正文 5 页面布局 盒子模型 布局标签 6 表格、表单标签 表格标签 表单标签 表单项 …

Positive证书是什么?

Positive SSL是全球著名CA Sectigo的子品牌&#xff0c; 也是目前全球签发量最高的商业SSL证书。价格低&#xff0c;安全性高&#xff0c;在个人网站和中小型企业网站中拥有极高的占有率。 Positive SSL证书包括DV SSL&#xff0c; EV SSL&#xff0c;也是唯一支持IP地址加密的…

第十六次CCF计算机软件能力认证

第一题&#xff1a;小中大 在数据分析中&#xff0c;最小值最大值以及中位数是常用的统计信息。 老师给了你 n 个整数组成的测量数据&#xff0c;保证有序&#xff08;可能为升序或降序)&#xff0c;可能存在重复的数据。 请统计出这组测量数据中的最大值、中位数以及最小值&am…

使用HTTP隧道时如何应对目标网站的反爬虫监测?

在进行网络抓取时&#xff0c;我们常常会遇到目标网站对反爬虫的监测和封禁。为了规避这些风险&#xff0c;使用代理IP成为一种常见的方法。然而&#xff0c;如何应对目标网站的反爬虫监测&#xff0c;既能保证数据的稳定性&#xff0c;又能确保抓取过程的安全性呢&#xff1f;…

【计算机网络】TCP协议超详细讲解

文章目录 1. TCP简介2. TCP和UDP的区别3. TCP的报文格式4. 确认应答机制5. 超时重传6. 三次握手7. 为什么两次握手不行?8. 四次挥手9. 滑动窗口10. 流量控制11. 拥塞控制12. 延时应答13. 捎带应答14. 面向字节流15. TCP的连接异常处理 1. TCP简介 TCP协议广泛应用于可靠性要求…

Fortinet安全专家问答实录|如何防护暴力破解、撞库攻击

黑客攻防&#xff0c;一个看似神秘&#xff0c;但却必不可缺的领域。近期&#xff0c;全球网络与安全融合领域领导者Fortinet&#xff08;Nasdaq&#xff1a;FTNT&#xff09;&#xff0c;开启了Fortinet DEMO DAY系列实战攻防演练线上直播&#xff0c;让人人都能零距离观摩黑客…

关于ETL的两种架构(ETL架构和ELT架构) qt

&#xfeff;ETL&#xff0c;是英文 Extract-Transform-Load 的缩写&#xff0c;用来描述将数据从来源端经过抽取&#xff08;extract&#xff09;、转换&#xff08;transform&#xff09;、加载&#xff08;load&#xff09;至目的端的过程。ETL一词较常用在数据仓库&#xf…

【flink】使用flink-web-ui提交作业报错

使用WebUI提交作业出现错误。 错误截图&#xff1a; 弹框信息&#xff1a; Server Response Message: org.apache.flink.runtime.rest.handler.RestHandlerException: Could not execute application.at org.apache.flink.runtime.webmonitor.handlers.JarRunHandler.lambda$h…