深入理解Java中Transactional在不同方法间的穿透性及rollbackFor参数的应用

在线工具站
  • 推荐一个程序员在线工具站:程序员常用工具(http://cxytools.com),有时间戳、JSON格式化、文本对比、HASH生成、UUID生成等常用工具,效率加倍嘎嘎好用。
程序员资料站
  • 推荐一个程序员编程资料站:程序员的成长之路(http://cxyroad.com),收录了一些列的技术教程、各大面试专题,还有常用开发工具的教程。
小报童专栏精选Top100
  • 推荐一个小报童专栏导航站:小报童精选Top100(http://xbt100.top),收录了生财有术项目精选、AI海外赚钱、纯银的产品分析等专栏,陆续会收录更多的专栏,欢迎体验~

在Java企业级开发中,Spring框架提供的@Transactional注解是我们实现事务管理的一个重要工具。
事务管理确保了一系列操作要么全部成功,要么全部失败,从而保持数据的一致性和完整性。
然而,在实际使用@Transactional时,经常会遇到事务穿透性和rollbackFor参数的相关问题。

一、事务的基本概念

1. 什么是事务

事务(Transaction)是指一组操作的集合,这些操作要么全部成功,要么全部失败,是一个不可分割的工作单位。事务具有以下四个特性(ACID):

  • 原子性(Atomicity): 事务中的所有操作要么全部完成,要么全部不完成。
  • 一致性(Consistency): 事务完成后,数据库从一个一致性状态转移到另一个一致性状态。
  • 隔离性(Isolation): 并发执行的事务之间彼此隔离,一个事务的执行不能被其他事务干扰。
  • 持久性(Durability): 一旦事务提交,其结果在数据库中是永久性的,即使系统崩溃也不会丢失。

2. Spring中的事务管理

Spring框架通过@Transactional注解提供了声明式事务管理。通过在方法上使用该注解,可以让Spring自动管理该方法的事务。

@Service
public class MyService {@Transactionalpublic void performTransaction() {// 事务操作}
}

二、事务在不同方法间的穿透性

1. 什么是事务穿透性

事务穿透性指的是在一个事务方法内部调用另一个事务方法时,事务是如何传播和管理的。Spring提供了多种事务传播行为(Propagation),用于控制事务的传播方式。

2. 事务传播行为类型

Spring定义了七种事务传播行为,常用的有以下几种:

  • REQUIRED: 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
  • REQUIRES_NEW: 创建一个新的事务,如果当前存在事务,则将当前事务挂起。
  • NESTED: 如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则与REQUIRED相同。
@Service
public class MyService {@Transactional(propagation = Propagation.REQUIRED)public void methodA() {// 操作AmethodB();// 操作B}@Transactional(propagation = Propagation.REQUIRES_NEW)public void methodB() {// 操作C}
}

在上面的例子中,methodA使用了REQUIRED传播行为,而methodB使用了REQUIRES_NEW传播行为。当methodA调用methodB时,methodA的事务会被挂起,methodB会在一个新的事务中执行。

3. 事务传播行为的应用场景

  • REQUIRED: 适用于大多数情况,确保操作在同一个事务中执行。
  • REQUIRES_NEW: 适用于需要在当前事务外执行的操作,例如记录日志或发送通知。
  • NESTED: 适用于需要嵌套事务的情况,例如在一个事务内部执行一个子事务,并希望子事务失败时不会影响父事务的提交。

三、rollbackFor参数的应用

1. 什么是rollbackFor参数

rollbackFor参数用于指定哪些异常会触发事务回滚。默认情况下,Spring只会在遇到未检查异常(RuntimeException及其子类)时回滚事务,对于已检查异常(Exception及其子类)则不会回滚事务。

2. rollbackFor参数的使用

通过rollbackFor参数,我们可以指定需要回滚事务的异常类型。例如:

@Service
public class MyService {@Transactional(rollbackFor = Exception.class)public void performTransaction() throws Exception {// 操作Aif (someCondition) {throw new Exception("需要回滚的异常");}// 操作B}
}

在上面的例子中,performTransaction方法指定了rollbackFor = Exception.class,意味着当抛出Exception时会回滚事务。

3. rollbackFor参数的应用场景

rollbackFor参数适用于以下场景:

  • 业务逻辑异常: 例如,某些业务规则未被满足时需要回滚事务。
  • 第三方服务异常: 例如,调用外部API失败时需要回滚事务。
  • 数据校验异常: 例如,数据格式不正确或不符合业务要求时需要回滚事务。

四、实例分析

1. 案例背景

假设我们有一个银行转账系统,需要实现从一个账户转账到另一个账户的功能。我们需要保证转账操作的原子性,即要么全部成功,要么全部失败。

2. 代码实现

@Service
public class BankService {@Autowiredprivate AccountRepository accountRepository;@Transactionalpublic void transfer(Long fromAccountId, Long toAccountId, BigDecimal amount) throws Exception {// 减少付款账户的余额Account fromAccount = accountRepository.findById(fromAccountId).orElseThrow();fromAccount.setBalance(fromAccount.getBalance().subtract(amount));accountRepository.save(fromAccount);// 增加收款账户的余额addAmountToAccount(toAccountId, amount);}@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)public void addAmountToAccount(Long accountId, BigDecimal amount) throws Exception {// 增加收款账户的余额Account toAccount = accountRepository.findById(accountId).orElseThrow();toAccount.setBalance(toAccount.getBalance().add(amount));accountRepository.save(toAccount);// 模拟异常if (amount.compareTo(BigDecimal.ZERO) < 0) {throw new Exception("无效的转账金额");}}
}

在这个例子中,transfer方法使用了REQUIRED传播行为,而addAmountToAccount方法使用了REQUIRES_NEW传播行为并指定了rollbackFor = Exception.class。当transfer方法调用addAmountToAccount方法时,如果addAmountToAccount方法抛出异常,则该方法的事务会回滚,但transfer方法的事务不会回滚,从而实现了事务的独立性和灵活性。

五、总结

本文深入解析了Java中@Transactional注解在不同方法间的穿透性及rollbackFor参数的应用。

通过理解事务传播行为,我们可以更好地控制事务的传播方式,实现复杂的事务管理逻辑。

同时,通过rollbackFor参数,我们可以指定哪些异常会触发事务回滚,从而确保数据的一致性和完整性。

在实际开发中,合理应用这些知识,可以有效提升应用的稳定性和可靠性。

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

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

相关文章

使用 Vue 和 Ant Design 实现抽屉效果的模块折叠功能

功能描述&#xff1a; 有两个模块&#xff0c;点击上面模块的收起按钮时&#xff0c;上面的模块可以折叠&#xff0c;下面的模块随之扩展 代码实现&#xff1a; 我们在 Vue 组件中定义两个模块的布局和状态管理&#xff1a; const scrollTableY ref(560); // 表格初始高度…

【HTML】格式化文本 pre 标签

文章目录 <pre> 元素中的文本以等宽字体显示&#xff0c;文本保留空格和换行符。 <pre> 元素支持 HTML 中的全局属性和事件属性。 示例&#xff1a; <pre> pre 元素中的文本 以等宽字体显示&#xff0c; 并且同时保留 空格 和 换行符。 </pre&…

git创建新分支

在Git中&#xff0c;要创建一个新的分支&#xff0c;可以使用以下命令&#xff1a; git branch <branch-name>这将创建一个名为 <branch-name> 的新分支&#xff0c;但它将仍然停留在当前分支上。要切换到新创建的分支&#xff0c;可以使用以下命令&#xff1a; …

分类模型:MATLAB判别分析

1. 判别分析简介 判别分析&#xff08;Discriminant Analysis&#xff09; 是一种统计方法&#xff0c;用于在已知分类的样本中构建分类器&#xff0c;并根据特征变量对未知类别的样本进行分类。常见的判别分析方法包括线性判别分析&#xff08;Linear Discriminant Analysis, …

人工智能的潜在威胁:罗曼·扬波尔斯基对AGI的警示

随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;技术正迅速成为人类社会不可或缺的一部分。然而&#xff0c;随着人工智能技术的发展&#xff0c;一些科学家对其潜在的危险表示了担忧。本文将深入探讨计算机科学家罗曼扬波尔斯基对人工智能特别是人工通用智…

兔子与兔子

#include <bits/stdc.h> #define ull unsigned long long using namespace std; //const ll P1e97; const ull base131; //挺好用的一个hash base const int N1e610; int m; ull sum[N],powe[N]; char s[N]; int main() { scanf( "%s",s1 ); powe[0]…

Python学习笔记7:入门知识(七)

前言 之前说过我更换了新的学习路线&#xff0c;现在是根据官方文档和书籍Python crash course来进行学习的&#xff0c;在目前的学习中&#xff0c;对于之前的知识有一些遗漏&#xff0c;这里进行补充。 学习资料有两个&#xff0c;书籍中文版PDF&#xff0c;关注我私信发送…

k8s_示例_根据CPU使用率自动扩展Pod数量并使Pod分布在不同节点

我们从制作测试用镜像开始,后续一步一步实现在k8s中使pod根据cpu用量自动扩展pod个数。 知识准备 在做这个示例之前,需要了解k8s(也叫kubernetes)基本原理,了解k8s是用来干嘛的即可,以及deployment、service、hpa、镜像、docker等概念。不然会有些晕的,不知道这些配置和…

2024年本科毕业设计优秀节选

可塑之才&#xff0c;大有前途。排名不分先后。世界是你们的。祝贺你们顺利毕业&#xff01; W某天&#xff0c;电子数据存储与访问控制机制设计&#xff0c;电气智能20-5&#xff0c;视频链接&#xff1a; 【PBFT-Caliper压测-哔哩哔哩】 PBFT-Caliper压测_哔哩哔哩_bilibil…

Joplin Typora 粘贴图片 | 当使用Typora作为Joplin编辑器时,如何粘贴图片并上传到Joplin服务器,替换链接

一、背景 当我们使用Joplin时&#xff0c;上传图片时会自动上传到Joplin服务器并替换链接 但是Joplin的编辑器不好用&#xff0c;我更习惯用Typora来编辑&#xff0c; 然而Typora中上传的图片只能在本地&#xff0c;无法上传到Joplin服务器&#xff0c;在其他客户端也看不到图片…

QT向已有ZIP中追加文件

向已有ZIP中追加文件&#xff0c;使用qt自带的QZipWriter和quazip库均失败了&#xff0c;要么格式损坏、要么ZIP里面的原有的文件清空了 使用7z.exe可以实现 : 指令 7z.exe a A.zip B.txt&#xff0c;使用代码控制如下 #include <QCoreApplication> #include <QFile…

C#——方法函数详情

方法(函数) C#是面向对象的,所以C#中的方法也是相对于对象来说的,是指某个对象的行为,比如,有一个动物的类,兔子是这个动物类里的一个对象,那么跳这个行为就是兔子这个对象的方法了.其实也就是C中的函数(C是面向过程的,叫函数). 方法: 就是把一系列相关的代码组织到一块 用于…

语法07 C++ 程序中的除法和求余

程序中的除法 int / int int double / int double int / double double double / double double 规律总结 只要除号任意一边出现了double类型&#xff0c;结果就是double类型 只有除号两边都是int类型&#xff0c;结果才是int类型 这个规律也适用于加法减法和乘法 …

服务器端渲染(SSR)

什么是服务器端渲染 ssr SSR 的全称是 Server Side Rendering&#xff0c;对应的中文名称是:服务端渲染&#xff0c;也就是将页面的 html 生成工作放在服务端进行。 网页通常是通过后端路由直接给客户端的。也就是说网页的html一般是后端服务器里通过模板引擎渲染好后再交给前…

操作系统入门系列-MIT6.828(操作系统工程)学习笔记(七)---- 系统调用函数与GDB(Lab: system calls)

系列文章目录 操作系统入门系列-MIT6.828&#xff08;操作系统工程&#xff09;学习笔记&#xff08;一&#xff09;---- 操作系统介绍与接口示例 操作系统入门系列-MIT6.828&#xff08;操作系统工程&#xff09;学习笔记&#xff08;二&#xff09;---- 课程实验环境搭建&am…

【设计模式之享元模式 -- C++】

享元模式 – 共享对象&#xff0c;节省内存 享元模式&#xff08;Flyweight Pattern&#xff09;是一种用于性能优化的模式&#xff0c;其核心是运用共享技术来有效支持大量细粒度的对象。享元模式可以避免大量非常相似类的开销。在程序设计中&#xff0c;有时我们需要生成大量…

vue-router 源码分析——6.命名路由

这是对vue-router 3 版本的源码分析。 本次分析会按以下方法进行&#xff1a; 按官网的使用文档顺序&#xff0c;围绕着某一功能点进行分析。这样不仅能学习优秀的项目源码&#xff0c;更能加深对项目的某个功能是如何实现的理解。这个对自己的技能提升&#xff0c;甚至面试时…

Python 围棋游戏【含Python源码 MX_008期】

简介&#xff1a; 围棋&#xff0c;源自中国&#xff0c;是一种两人对弈的策略棋类游戏。它被认为是世界上最复杂的棋类游戏之一&#xff0c;因为它的规则简单&#xff0c;但变化复杂多样。围棋的游戏目标是在棋盘上占领更多的地盘&#xff0c;并用自己的棋子围住对手的棋子&am…

docker-compose harbor 2.11

harbor 前言 “Harbor” 是一个用于管理容器镜像的开源仓库项目。由 VMware 开发和维护,Harbor 提供一个企业级的 Docker 镜像仓库,具有丰富的功能,包括: 镜像管理:提供存储和分发 Docker 镜像的能力。安全性:支持镜像签名和漏洞扫描,确保镜像的安全性。身份认证:集成…

项目代码导出到word脚本

需求 之前课程需求&#xff0c;需要将项目代码导出到一个word进行存档。当时就写了这个脚本来进行导出&#xff0c;现在毕业论文又有这个需求了&#xff0c;将这个脚本总结并帮助更多的人。 项目地址github项目&#xff0c;如果有人想更加完美的可以进行修改。 实现与操作 …