深入了解 Spring boot的事务管理机制:掌握 Spring 事务的几种传播行为、隔离级别和回滚机制,理解 AOP 在事务管理中的应用

🎉🎉欢迎光临,终于等到你啦🎉🎉

🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀

🌟持续更新的专栏《Spring 狂野之旅:从入门到入魔》 🚀

本专栏带你从Spring入门到入魔 

这是苏泽的个人主页可以看到我其他的内容哦👇👇

努力的苏泽icon-default.png?t=N7T8http://suzee.blog.csdn.net/


目录

介绍

1.1 Spring 事务管理的重要性

1.2 目标和范围

Spring 事务基础

2.1 事务概述

2.2 事务管理器

2.3 事务定义和注解

事务角色

事务相关配置

事务传播行为

1. REQUIRED 传播行为

2. REQUIRES_NEW 传播行为

3. SUPPORTS 传播行为

4. NOT_SUPPORTED 传播行为

5. MANDATORY 传播行为

6. NEVER 传播行为

​编辑

隔离级别

1. READ_UNCOMMITTED 隔离级别

2. READ_COMMITTED 隔离级别

3. REPEATABLE_READ 隔离级别

4. SERIALIZABLE 隔离级别

事务原理

aop/动态代理

事务管理

对于编程式事务管理:

对于声明式事务管理:

实例

TransactionInterceptor 事务拦截处理


介绍

1.1 Spring 事务管理的重要性

在应用程序中,事务管理是确保数据的一致性和完整性的重要组成部分。Spring 事务管理提供了一种可靠且灵活的方式来管理事务,确保在数据库操作过程中的原子性、一致性、隔离性和持久性。

Spring 事务管理的重要性包括:

  • 数据库一致性:通过事务管理,可以确保数据库操作的原子性,即要么所有操作都成功提交,要么全部回滚,从而保持数据的一致性。
  • 错误处理和回滚:事务管理使得在发生错误时能够回滚事务,确保数据的完整性,以及在异常情况下进行适当的错误处理。
  • 并发控制:通过定义适当的隔离级别,事务管理可以处理并发访问数据库的问题,避免数据冲突和不一致性。
  • 扩展性和灵活性:Spring 事务管理提供了多种配置选项和编程方式,可以根据应用程序的需求进行灵活配置和管理。
1.2 目标和范围

Spring 事务管理的目标是确保在应用程序中的数据库操作过程中,能够实现以下目标:

  • 原子性(Atomicity):事务中的所有操作要么全部成功执行并提交,要么全部失败并回滚,确保数据库的一致性。
  • 一致性(Consistency):事务的执行过程中,数据库从一个一致的状态转变为另一个一致的状态,不会破坏数据的完整性。
  • 隔离性(Isolation):多个并发事务之间应该相互隔离,每个事务的操作应该看起来像是在独立执行,避免数据冲突和不一致性。
  • 持久性(Durability):一旦事务提交,其对数据库的修改应该是永久性的,即使在系统故障或重启后也能够恢复。

Spring 事务管理的范围包括:

  • 支持多种事务管理方式:Spring 提供了多种事务管理方式,包括编程式事务管理和声明式事务管理,以适应不同的应用场景和开发需求。
  • 集成多种事务管理器:Spring 可以与各种事务管理器集成,包括本地 JDBC 事务、JTA 分布式事务、Hibernate 事务等,以便与不同的持久化框架和数据库进行交互。
  • 提供注解和 XML 配置支持:Spring 允许使用注解或 XML 配置的方式来定义和管理事务,使得事务管理更加灵活和便捷。

Spring 事务基础

2.1 事务概述

Spring 事务是一组数据库操作的逻辑单元,具有原子性和一致性。事务由一系列操作组成,这些操作要么全部成功执行并提交,要么全部失败并回滚。

Spring 事务的关键概念包括:

  • 事务管理器(Transaction Manager):事务管理器是 Spring 提供的一个接口,用于管理事务的开始、提交和回滚操作。它与底层的数据库或持久化框架进行交互,并确保事务的正确执行。
  • 事务定义(Transaction Definition):事务定义定义了事务的属性,如隔离级别、传播行为、超时设置等。它可以通过编程方式或声明式方式来定义。
  • 事务状态(Transaction Status):事务状态表示当前事务的状态,包括已提交、已回滚或进行中等。通过事务状态,可以对事务进行管理和控制。
  • 事务切面(Transaction Aspect):事务切面是应用程序中与事务相关的逻辑和功能的集合。它可以通过编程方式或声明式方式来定义和应用。
2.2 事务管理器

在 Spring 中,事务管理器(Transaction Manager)是用于管理事务的关键组件。事务管理器负责事务的开始、提交和回滚操作,并与底层的数据库或持久化框架进行交互。

Spring 提供了多种事务管理器的实现,包括:

  • DataSourceTransactionManager:用于管理基于 JDBC 的事务,与 JDBC DataSource 进行交互。
  • JpaTransactionManager:用于管理基于 JPA(Java Persistence API)的事务,与 JPA EntityManagerFactory 进行交互。
  • HibernateTransactionManager:用于管理基于 Hibernate 的事务,与 Hibernate SessionFactory 进行交互。
  • JtaTransactionManager:用于管理分布式事务,与 JTA(Java Transaction API)进行交互。

你可以根据应用程序所使用的持久化框架选择合适的事务管理器。

2.3 事务定义和注解

在 Spring 中,事务定义(Transaction Definition)用于定义事务的属性,如隔离级别、传播行为、超时设置等。事务定义可以通过编程方式或声明式方式来定义。

编程式事务定义是通过编写代码来显式地管理事务的开始、提交和回滚。你可以使用编程式事务管理的 API(如 TransactionTemplate)来定义事务的属性。

声明式事务定义是通过在方法或类级别上使用注解或 XML 配置来定义事务的属性。Spring 提供了 @Transactional 注解,用于在方法级别上定义事务的属性。你可以在需要进行事务管理的方法上添加 @Transactional 注解,并指定事务的属性。

事务的属性包括传播行为(Propagation)、隔离级别(Isolation)、只读标志(ReadOnly)、超时设置(Timeout)等。通过定义适当的事务属性,你可以控制事务的行为和特性。

例如,下面是一个使用 @Transactional 注解定义事务的例子:

@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
public void performTransaction() {// 事务操作
}

事务角色

事务相关配置

 

事务传播行为

1. REQUIRED 传播行为

  • 如果当前存在事务,则加入该事务中执行。
  • 如果当前没有事务,则创建一个新的事务执行。
  • 这是Spring默认的传播行为。

2. REQUIRES_NEW 传播行为

  • 总是创建一个新的事务,并挂起当前事务(如果存在)。
  • 在新的事务中执行方法,不受外部事务的影响。

3. SUPPORTS 传播行为

  • 如果当前存在事务,则加入该事务中执行。
  • 如果当前没有事务,则以非事务的方式执行。

4. NOT_SUPPORTED 传播行为

  • 总是以非事务的方式执行方法。
  • 如果当前存在事务,则将其挂起。

5. MANDATORY 传播行为

  • 如果当前存在事务,则加入该事务中执行。
  • 如果当前没有事务,则抛出异常。

6. NEVER 传播行为

  • 总是以非事务的方式执行方法。
  • 如果当前存在事务,则抛出异常。

 

隔离级别

1. READ_UNCOMMITTED 隔离级别

  • 最低的隔离级别,允许脏读、不可重复读和幻读的发生。
  • 一个事务可以读取另一个事务未提交的数据。

2. READ_COMMITTED 隔离级别

  • 保证一个事务修改的数据提交后才能被另一个事务读取。
  • 避免脏读的发生,但仍可能出现不可重复读和幻读。

3. REPEATABLE_READ 隔离级别

  • 保证一个事务不能读取另一个事务未提交的数据。
  • 避免脏读和不可重复读的发生,但仍可能出现幻读。

4. SERIALIZABLE 隔离级别

  • 最高的隔离级别,保证所有情况下都不会发生脏读、不可重复读和幻读。
  • 事务被处理为顺序执行,避免并发读写操作。

事务原理

aop/动态代理

Spring的事务抽象包括三个主要接口:PlatformTransactionManager、TransactionDefinition和TransactionStatus。

  • PlatformTransactionManager负责定义事务的边界,它确定了何时开始和结束一个事务。
  • TransactionDefinition负责定义事务的属性,包括隔离级别、传播行为等。它提供了对事务进行详细配置的能力。
     
  • PlatformTransactionManager根据TransactionDefinition的属性定义来开启相关的事务。在事务开始后到结束期间,TransactionStatus负责跟踪和管理事务的状态。通过TransactionStatus,我们可以对事务进行有限的控制。
     
  • 常用的TransactionDefinition的实现包括DefaultTransactionDefinition和TransactionTemplate。这两个主要用于编程式事务场景。另外,还有DefaultTransactionAttribute和RuleBasedTransactionAttribute,它们主要用于基于Spring AOP的声明式事务管理场景。RuleBasedTransactionAttribute允许同时指定多个回滚规则。
     
  • TransactionStatus的一个常见实现是DefaultTransactionStatus,它用于记录事务的状态信息。
  • PlatformTransactionManager的实现可以分为面向局部事务和面向全局事务两个分支。常用的面向局部事务的实现包括DataSourceTransactionManager(用于JDBC和MyBatis)和HibernateTransactionManager。它们提供了针对特定持久化框架的事务管理功能。

事务管理

对于编程式事务管理:

  1. 使用TransactionTemplate或直接使用底层的PlatformTransactionManager进行操作。
  2. 需要在代码中显式地编写事务管理的逻辑。
  3. 需要手动处理事务的开始、提交和回滚。
  4. 事务的管理逻辑与业务逻辑紧密耦合,导致代码的可读性和可维护性降低。
  5. 可以在更细粒度的代码块级别实现事务管理。

对于声明式事务管理:

  1. 建立在AOP(面向切面编程)之上,通过拦截目标方法前后的执行来实现事务管理。
  2. 通过配置文件或基于@Transactional注解的方式声明事务规则。
  3. 不需要在业务逻辑代码中编写事务管理的代码,保持业务代码的纯粹性。
  4. 事务的管理逻辑与业务逻辑解耦,提高了代码的可读性和可维护性。
  5. 最细粒度只能作用于方法级别,无法直接作用于代码块级别,但可以通过方法的粒度来实现类似的效果。

实例

假设我们有一个银行账户系统,其中涉及两个账户之间的转账操作,需要保证转账操作的原子性,即要么两个账户的金额同时发生变化,要么都不发生变化。

首先,我们需要使用数据库事务来确保转账操作的一致性。假设我们使用Spring框架来管理事务,代码如下所示:

@Transactional
public void transferAmount(String fromAccount, String toAccount, double amount) {try {// 1. 查询转出账户的余额double fromBalance = accountDao.getBalance(fromAccount);// 2. 查询转入账户的余额double toBalance = accountDao.getBalance(toAccount);// 3. 判断转出账户余额是否足够if (fromBalance < amount) {throw new InsufficientBalanceException("Insufficient balance in the source account.");}// 4. 扣除转出账户的金额accountDao.updateBalance(fromAccount, fromBalance - amount);// 5. 增加转入账户的金额accountDao.updateBalance(toAccount, toBalance + amount);// 6. 提交事务} catch (Exception e) {// 7. 出现异常,回滚事务throw new TransferException("Error occurred during the transfer.", e);}
}

我们使用@Transactional注解表示该方法需要在事务中执行。在方法内部,我们按照以下步骤进行转账操作:

  1. 查询转出账户的余额。
  2. 查询转入账户的余额。
  3. 判断转出账户余额是否足够,如果不足够,则抛出异常。
  4. 扣除转出账户的金额。
  5. 增加转入账户的金额。

在第6步之前,如果发生了异常,会跳转到第7步,即异常处理的代码块。在异常处理块中,我们抛出一个自定义的TransferException,并使用throw语句将异常继续抛出。这会触发Spring事务管理器的回滚机制,导致之前的数据库操作被撤销,从而恢复到事务开始之前的状态。

通过事务回滚机制,如果在转账过程中发生异常,例如转出账户余额不足,所有的数据库操作都会被回滚,确保数据的一致性。这样可以避免转账过程中数据发生不一致的情况。

TransactionInterceptor 事务拦截处理

通过 Pointcut 事务切点筛选出来的 Bean,会创建一个代理对象,Bean 内部肯定定义了 @Transactional 注解,如果是类上定义的 @Transactional 注解,每个方法都需要进行事务处理。代理对象的事务拦截处理在 TransactionInterceptor 拦截器中,实现了 MethodInterceptor 方法拦截器,也就是实现了 Object invoke(MethodInvocation invocation) 这个方法,一起来看看 TransactionInterceptor 这个类

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

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

相关文章

ElementUI两个小坑

1.form表单绑定的是一个对象&#xff0c;表单里的一个输入项是对象的一个属性之一&#xff0c;修改输入项&#xff0c;表单没刷新的问题&#xff0c; <el-form :model"formData" :rules"rules" ref"editForm" class"demo-ruleForm"…

拆解Spring boot:Springboot为什么如此丝滑而简单?源码剖析解读自动装配

&#x1f389;&#x1f389;欢迎光临&#xff0c;终于等到你啦&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;持续更新的专栏《Spring 狂野之旅&#xff1a;从入门到入魔》 &a…

【深度学习】线性回归

Linear Regression 一个例子线性回归机器学习中的表达评价函数好坏的度量&#xff1a;损失&#xff08;Loss&#xff09;损失函数&#xff08;Loss function&#xff09;哪个数据集的均方误差 (MSE) 高 如何找出最优b和w?寻找最优b和w如何降低损失 (Reducing Loss)梯度下降法梯…

Vue首屏优化方案

在Vue项目中&#xff0c;引入到工程中的所有js、css文件&#xff0c;编译时都会被打包进vendor.js&#xff0c;浏览器在加载该文件之后才能开始显示首屏。若是引入的库众多&#xff0c;那么vendor.js文件体积将会相当的大&#xff0c;影响首屏的体验。可以看个例子&#xff1a;…

Elasticsearch使用Kibana进行基础操作

一、Restful接口 Elasticsearch通过RESTful接口提供与其进行交互的方式。在ES中&#xff0c;提供了功能丰富的RESTful API的操作&#xff0c;包括CRUD、创建索引、删除索引等操作。你可以用你最喜爱的 web 客户端访问 Elasticsearch 。事实上&#xff0c;你甚至可以使用 curl …

java SSM在线学习网站系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java SSM在线学习网站系统是一套完善的web设计系统&#xff08;系统采用SSM框架进行设计开发&#xff0c;springspringMVCmybatis&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用…

COX回归影响因素分析的基本过程与方法

在科学研究中&#xff0c;经常遇到分类的结局&#xff0c;主要是二分类结局&#xff08;阴性/阳性&#xff1b;生存/死亡&#xff09;&#xff0c;研究者可以通过logistic回归来探讨影响结局的因素&#xff0c;但很多时候logistic回归方法无法使用。如比较两种手段治疗新冠肺炎…

AOP-面向切面编程

文章目录 AOP应用背景AOP介绍AOP七大术语切点表达式 AOP应用背景 一天&#xff0c;项目经理突然跟我说&#xff1a;官网后端管理系统需要增加“用户操作流水功能”&#xff01;啥&#xff0c;用户操作流水&#xff1f;对&#xff0c;记录后台管理用户的所有增删改查的操作&…

mac删除带锁标识的app

一 、我们这里要删除FortiClient.app 带锁 常规方式删除不掉带锁的 app【如下图】 二、删除命令&#xff0c;依次执行即可。 /bin/ls -dleO /Applications/FortiClient.app sudo /usr/bin/chflags -R noschg /Applications/FortiClient.app /bin/ls -dleO /Applications/Forti…

QT信号与槽实现方式

1、第一种实现方式 在QT开发工具UI界面先拖入按钮&#xff0c;然后鼠标右键拖入按钮&#xff0c;点击选中槽&#xff0c;在页面选着需要的信号&#xff0c;然后OK&#xff0c;随即将会跳转到类的.cpp文件&#xff0c;&#xff08;这种UI代码结合的方式&#xff0c;会自动去绑定…

【洛谷 P8637】[蓝桥杯 2016 省 B] 交换瓶子 题解(贪心算法)

[蓝桥杯 2016 省 B] 交换瓶子 题目描述 有 N N N 个瓶子&#xff0c;编号 1 ∼ N 1 \sim N 1∼N&#xff0c;放在架子上。 比如有 5 5 5 个瓶子&#xff1a; 2 , 1 , 3 , 5 , 4 2,1,3,5,4 2,1,3,5,4 要求每次拿起 2 2 2 个瓶子&#xff0c;交换它们的位置。 经过若干次…

AIGC笔记--关节点6D位姿按比例融合

1--核心代码 6D位姿一般指平移向量和旋转向量&#xff0c;Maya软件中关节点的6D位姿指的是相对平移向量和欧拉旋转向量&#xff1b; 为了按比例融合两个Pose&#xff0c;首先需要将欧拉旋转向量转换为旋转矩阵&#xff0c;在将旋转矩阵转换为四元数&#xff0c;利用球面线性插值…

react native常用插件

react-native-async-storage/async-storage 说明&#xff1a;AsyncStorage 是一个在 react-native 中轻量存储的库&#xff1b;跟 localStorage 类似&#xff0c;API 也几乎一样&#xff1b;存储的时候需要将存储内容转成字符串存储。 react-navigation/material-bottom-tabs …

如何在WordPress网站上设置多语言展示

在今天的全球化世界中&#xff0c;拥有多语言网站对于吸引更广泛的受众至关重要。前不就我们遇到Hostease的客户咨询我们的在线客服&#xff0c;他想要对他的wordpress网站支持多语言。我们提供给客户可以尝试以下的插件来支持多语言。 在本教程中&#xff0c;我们将逐步介绍如…

教你三指针拿捏链表翻转

类似上图&#xff0c;其实步骤很简单&#xff0c;用三个指针pre&#xff0c;cur&#xff0c;temp&#xff0c;看英文也知道具体含义&#xff0c;前向&#xff0c;当前&#xff0c;和用于保存剩余的链表 &#xff0c;具体看下图&#xff0c;很清晰 class Solution { public:List…

AI-逻辑回归模型

&#x1f606;&#x1f606;&#x1f606;感谢大家的支持~&#x1f606;&#x1f606;&#x1f606; 逻辑回归的应用场景 逻辑回归&#xff08;Logistic Regression&#xff09;是机器学习中的 一种分类模型 &#xff0c;逻辑回归是一种分类算法&#xff0c;虽然名字中带有回…

Java代码基础算法练习---2024.3.14

其实这就是从我学校的资源&#xff0c;都比较基础的算法题&#xff0c;先尽量每天都做1-2题&#xff0c;练手感。毕竟离我真正去尝试入职好的公司&#xff08;我指的就是中大厂&#xff0c;但是任重道远啊&#xff09;&#xff0c;仍有一定的时间&#xff0c;至少要等我升本之后…

LarkXR上新了 | Apollo多终端与XR体验的优化创新

作为领先的数字平行世界产品技术提供方&#xff0c;「Paraverse平行云」一直致力于为企业和开发者提供企业级实时云渲染解决方案。其多终端接入产品LarkXR Apollo&#xff0c;基于底层Runtime技术&#xff0c;实现了在Windows、Linux、MacOS、Android、iOS等多种操作系统下&…

机器硬件命令

一、查看机器核数 有以下几种方法 1、lscpu命令 lscpu命令可以显示关于CPU的信息&#xff0c;包括核数、线程数等。在终端中输入以下命令即可查看CPU核数&#xff1a;该命令会输出CPU每个物理插槽的核数。 lscpu | grep "Core(s) per socket" | awk {print $NF} …

[iOS]高版本MacOS运行低版本Xcode

Xcode 版本支持文档 目的&#xff1a; 在MacOS Sonoma 系统上安装 Xcode14.3.1 第一步 先在Xcode下载一个Xcode14.3.1的压缩包 第二步 本地解压Xcode&#xff0c;将外层目录名变更为Xcode_14.3.1&#xff0c;将文件拷贝到 /Applications目录下。 第三步 变更xcode-sel…