深入解析 Spring 框架中的事务传播行为

目录

(一)REQUIRED

(二)SUPPORTS

(三)MANDATORY

(四)REQUIRES_NEW

(五)NOT_SUPPORTED

(六)NEVER

(七)NESTED


在 Spring 框架中,事务管理是一个至关重要的部分,而事务传播行为则是其中的核心概念之一。它决定了事务在多个方法调用之间的传播方式,对于确保数据的一致性和完整性具有关键作用。下面将详细介绍 Spring 框架中的七种事务传播行为,并结合使用场景说明其重要性。

(一)REQUIRED

  1. 定义:如果当前存在事务,就加入该事务;如果当前没有事务,就创建一个新的事务。这是最常见的选择,也是 Spring 的默认传播行为。
  2. 使用场景示例:在一个电商系统中,用户下单操作涉及订单创建、库存扣除和支付记录等多个步骤。这些步骤需要在同一个事务中完成,以确保数据的一致性。如果在某个步骤出现异常,整个事务应该回滚。此时,可以使用 REQUIRED 传播行为来保证这些操作在同一个事务中执行。例如:
@Service
public class OrderService {@Autowiredprivate InventoryService inventoryService;@Autowiredprivate PaymentService paymentService;@Transactional(propagation = Propagation.REQUIRED)public void createOrder(Order order) {inventoryService.reduceStock(order.getProductId(), order.getQuantity());paymentService.processPayment(order.getAmount());// 其他订单处理逻辑}
}

在这个例子中,createOrder 方法使用了 REQUIRED 传播行为。如果调用该方法时已经存在一个事务(例如,在另一个服务方法中开启了事务),那么 createOrder 方法将加入到这个已有的事务中;如果没有现有的事务,它将创建一个新的事务来执行订单创建的逻辑。

(二)SUPPORTS

  1. 定义:如果当前存在事务,就加入该事务;如果当前没有事务,就以非事务方式执行。
  2. 使用场景示例:在一些对性能要求较高且不需要强制事务保证的场景中,可以使用 SUPPORTS 传播行为。例如,在一个日志记录系统中,记录日志操作通常不需要事务支持,但如果在事务环境中调用日志记录方法,可以让它参与到当前事务中。假设有一个系统,在进行业务操作的同时需要记录一些日志信息到数据库。可以使用 SUPPORTS 传播行为的服务方法来实现:
@Service
public class LoggingService {@Autowiredprivate LogRepository logRepository;@Transactional(propagation = Propagation.SUPPORTS)public void recordLog(String message) {Log log = new Log();log.setMessage(message);log.setTimestamp(new Date());logRepository.save(log);}
}

当在事务环境中调用 recordLog 方法时,它会参与到当前事务中;如果在非事务环境中调用,它会以非事务的方式执行,不会开启新的事务。

(三)MANDATORY

  1. 定义:如果当前存在事务,就加入该事务;如果当前没有事务,就抛出异常。
  2. 使用场景示例:适用于必须依赖于外部事务才能执行的场景。例如,在银行转账系统中,转账操作需要在账户服务的事务中进行,以确保两个账户的余额更新操作要么同时成功,要么同时失败。假设有一个账户服务类:
@Service
public class AccountService {@Autowiredprivate AccountRepository accountRepository;@Transactional(propagation = Propagation.MANDATORY)public void transfer(Long fromAccountId, Long toAccountId, BigDecimal amount) {Account fromAccount = accountRepository.findById(fromAccountId);Account toAccount = accountRepository.findById(toAccountId);fromAccount.setBalance(fromAccount.getBalance().subtract(amount));toAccount.setBalance(toAccount.getBalance().add(amount));accountRepository.save(fromAccount);accountRepository.save(toAccount);}
}

当调用 transfer 方法时,如果当前没有事务存在,就会抛出异常,因为这个方法必须在事务环境中执行,以确保转账操作的原子性。

(四)REQUIRES_NEW

  1. 定义:总是创建一个新的事务。如果当前存在事务,就把当前事务挂起。
  2. 使用场景示例:在一些需要独立于当前事务执行的操作中非常有用。例如,在一个订单系统中,创建订单后需要发送一封确认邮件。发送邮件的操作应该在一个新的事务中执行,以避免邮件发送失败影响订单的创建。假设有一个邮件服务类:
@Service
public class EmailService {@Autowiredprivate EmailRepository emailRepository;@Transactional(propagation = Propagation.REQUIRES_NEW)public void sendConfirmationEmail(Order order) {Email email = new Email();email.setTo(order.getCustomerEmail());email.setSubject("Order Confirmation");email.setBody("Your order has been processed.");emailRepository.save(email);}
}

sendConfirmationEmail 方法被调用时,无论调用者是否在事务中,它都会创建一个新的事务来执行发送邮件的操作。这样即使邮件发送失败,也不会影响到订单的创建事务。

(五)NOT_SUPPORTED

  1. 定义:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
  2. 使用场景示例:适用于那些不应该与现有事务关联的操作,比如读取数据或执行一些不需要事务支持的计算任务。例如,在一个数据分析系统中,查询某个统计数据的方法可以使用 NOT_SUPPORTED 传播行为,以避免对正在进行的事务造成不必要的干扰:
@Service
public class DataAnalysisService {@Autowiredprivate DataRepository dataRepository;@Transactional(propagation = Propagation.NOT_SUPPORTED)public BigDecimal calculateAverageValue() {List<Data> allData = dataRepository.findAll();BigDecimal sum = allData.stream().map(Data::getValue).reduce(BigDecimal.ZERO, BigDecimal::add);return sum.divide(new BigDecimal(allData.size()), 2, RoundingMode.HALF_UP);}
}

在这个例子中,calculateAverageValue 方法在执行时会挂起任何现有的事务,以非事务的方式计算平均值。

(六)NEVER

  1. 定义:以非事务方式执行,如果当前存在事务,则抛出异常。
  2. 使用场景示例:用于确保某个操作绝对不与现有事务关联的场景。例如,在一个系统中,某些只读操作可能不希望受到事务的影响,因为它们可能会被频繁调用且不需要事务的一致性保证。假设有一个缓存服务类,其中的缓存加载方法可以使用 NEVER 传播行为:
@Service
public class CacheService {@Autowiredprivate CacheManager cacheManager;@Transactional(propagation = Propagation.NEVER)public void loadCache() {// 从外部数据源加载数据到缓存中的逻辑}
}

loadCache 方法被调用时,如果当前存在事务,就会抛出异常,因为它不允许在事务环境中执行。

(七)NESTED

  1. 定义:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则按 REQUIRED 属性执行。
  2. 使用场景示例:在一些复杂的业务场景中,需要在现有事务的基础上再开启一个子事务,以实现更细粒度的事务控制。例如,在一个大型项目中,某个模块可能需要在另一个模块的事务基础上进行一些额外的操作,但又希望这些操作有自己的事务边界。假设有一个子模块服务类:
@Service
public class SubModuleService {@Autowiredprivate SubModuleRepository subModuleRepository;@Transactional(propagation = Propagation.NESTED)public void performSubOperation(Long subModuleId) {SubModule subModule = subModuleRepository.findById(subModuleId);// 进行子模块相关的操作逻辑}
}

performSubOperation 方法在现有事务中被调用时,它会在一个嵌套事务中执行;如果没有现有事务,它会像使用 REQUIRED 传播行为一样创建一个新的事务。

Spring 框架中的七种事务传播行为为开发者提供了灵活的事务管理机制,能够适应各种不同的业务场景。通过合理选择和应用这些传播行为,可以更好地确保数据的一致性和完整性,提高系统的可靠性和稳定性。在实际开发中,需要根据具体的业务需求仔细考虑和选择合适的事务传播行为,以实现最佳的事务管理效果。

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

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

相关文章

60,【1】BUUCF web [RCTF2015]EasySQL1

先查看源码 1&#xff0c;changepwd&#xff08;修改密码&#xff09; <?php // 开启会话&#xff0c;以便使用会话变量 session_start();// 设置页面的内容类型为 HTML 并使用 UTF-8 编码 header("Content-Type: text/html; charsetUTF-8");// 引入配置文件&…

高并发内存池_CentralCache(中心缓存)和PageCache(页缓存)申请内存的设计

三、CentralCache&#xff08;中心缓存&#xff09;_内存设计 &#xff08;一&#xff09;Span的创建 // 页编号类型&#xff0c;32位下是4byte类型&#xff0c;64位下是8byte类型 // #ifdef _WIN64 typedef unsigned long long PageID; #else _WIN32 typedef size_t PageI…

2024年终总结-行到水穷处,坐看云起时

依然是——关于我 我&#xff0c;坐标山东青岛&#xff0c;一位无名的Java Coder&#xff0c;你可以叫我Debug.c亦或者种棵代码技术树。在此不过多赘述关于我&#xff0c;更多的关于我请移步我的2023年年终总结。 2023年终总结-轻舟已过万重山 2024年OKR完成情况 2023年年末…

AI编程工具使用技巧:在Visual Studio Code中高效利用阿里云通义灵码

AI编程工具使用技巧&#xff1a;在Visual Studio Code中高效利用阿里云通义灵码 前言一、通义灵码介绍1.1 通义灵码简介1.2 主要功能1.3 版本选择1.4 支持环境 二、Visual Studio Code介绍1.1 VS Code简介1.2 主要特点 三、安装VsCode3.1下载VsCode3.2.安装VsCode3.3 打开VsCod…

1月21日星期二今日早报简报微语报早读

1月21日星期二&#xff0c;农历腊月廿二&#xff0c;早报#微语早读。 1、多地官宣&#xff1a;2025年可有序、限时或在限定区域燃放烟花爆竹&#xff1b; 2、TikTok恢复在美服务&#xff1b;特朗普提出继续运营TikTok方案&#xff0c;外交部&#xff1a;若涉及收购中国企业应…

计算机组成原理——数据表示(一)

生活是一道长长的旅程&#xff0c;充满了挑战和困难。然而&#xff0c;我们必须坚持下去&#xff0c;努力前进。无论遇到什么困难&#xff0c;我们都要勇敢面对&#xff0c;永不放弃。只有通过不断的努力和坚持&#xff0c;我们才能够取得成功。在这个旅程中&#xff0c;我们可…

强化学习入门--基本概念

强化学习基本概念 grid-world example 这个指的是一个小机器人&#xff08;agent&#xff09;在一个网格区域&#xff08;存在边界&#xff09;&#xff0c;网格中存在需要躲避的格子和目标格子&#xff0c;我们的目的就是找到到达目标格子的最短路径 state 表示智能体相对…

STMCubeMX配置STM32F103ZET6

1 配置时钟 配置RCC。 配置 SYS。将Timebase Source配置为TIM1, SysTick留给FreeRTOS用。 注意: 由于第一次配置的时候忘记配置这个步骤,导致工程第一次烧录成功后,后面一直无法烧录,报以下错误: keil no target connect Error: Flash Download failed - Target DLL h…

Leetcode:2239

1&#xff0c;题目 2&#xff0c;思路 循环遍历满足条件就记录&#xff0c;最后返回结果值 3&#xff0c;代码 public class Leetcode2239 {public static void main(String[] args) {System.out.println(new Solution2239().findClosestNumber(new int[]{-4, -2, 1, 4, 8})…

C语言之斗地主游戏

&#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 ​ C语言之斗地主游戏 目录 程序概述程序设计 Card类CardGroup类Player类LastCards类Land…

python编程-OpenCV(图像读写-图像处理-图像滤波-角点检测-边缘检测)图像变换

形态变换 图像处理中的形态学操作是处理图像结构的有效方法。以下是一些常见的形态学操作的介绍及其在 OpenCV 中的实现示例。 1. 腐蚀&#xff08;Erosion&#xff09; 腐蚀操作通过消除图像边界来减少图像中的白色区域&#xff08;前景&#xff09;&#xff0c;使物体的边…

【Prometheus】PromQL进阶用法

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

计算机网络介质访问控制全攻略:从信道划分到协议详解!!!

一、信道划分介质访问控制 介质访问控制&#xff1a;多个节点共享同一个“总线型”广播信道时&#xff0c;可能发生“信号冲突” 应该怎么控制各节点对传输介质的访问&#xff0c;才能减少冲突&#xff0c;甚至避免冲突? 时分复用(TDM) 时分复用&#xff1a;将时间分为等长的“…

Prometheus部署及linux、mysql、monog、redis、RocketMQ、java_jvm监控配置

Prometheus部署及linux、mysql、monog、redis、RocketMQ、java_jvm监控配置 1.Prometheus部署1.2.Prometheus修改默认端口 2.grafana可视化页面部署3.alertmanager部署4.监控配置4.1.主机监控node-exporter4.2.监控mysql数据库mysqld_exporter4.3.监控mongod数据库mongodb_expo…

基于tldextract提取URL里的子域名、主域名、顶级域

TLD是TopLevel Domain的缩写。‌tldextract‌ 是一个用于从URL中提取子域、主域名和顶级域&#xff08;TLD&#xff09;的Python库。它利用公共后缀列表&#xff08;Public Suffix List&#xff09;来确保即使是复杂或不常见的URL结构也能被正确解析。tldextract能够处理包括IC…

常见Arthas命令与实践

Arthas 官网&#xff1a;https://arthas.aliyun.com/doc/&#xff0c;官方文档对 Arthas 的每个命令都做出了介绍和解释&#xff0c;并且还有在线教程&#xff0c;方便学习和熟悉命令。 Arthas Idea 的 IDEA 插件。 这是一款能快速生成 Arthas命令的插件&#xff0c;可快速生成…

win32汇编环境,对多行编辑框添加或删除文本

;运行效果 ;win32汇编环境,对多行编辑框添加或删除文本 ;主要要先设置文本的开始点与结束点&#xff0c;然后把一段文本顶替上去。没有添加文本或删除文本的概念&#xff0c;只有顶替。如果开始点与结束点都是前面文本的长度值&#xff0c;则成了从后面添加文本的效果。如果结束…

CSDN年度回顾:技术征途上的坚实步伐

嘿&#xff0c;时光过得可真快呀&#xff0c;就像那匹跑得飞快的白马&#xff0c;嗖的一下&#xff0c;2024 年的日历就这么悄无声息地翻到了最后一页。这会儿我回头看看在 CSDN 上度过的这一年&#xff0c;心里那叫一个感慨万千&#xff0c;满满的都是喜悦&#xff0c;就像心里…

人脸识别打卡系统--基于QT(附源码)

逃离舒适区 项目源代码放在我的仓库中&#xff0c;有需要自取 项目地址 https://gitcode.com/hujiahangdewa/Face_recognition.git 文章目录 一、项目结构分析二、服务器的搭建三、客户端的搭建四、人脸识别库的申请五、基于人脸识别库的识别判断六、QT人脸识别----调用百度ai…

人工智能在数字化转型中的角色:从数据分析到智能决策

引言 在数字化转型浪潮中&#xff0c;人工智能&#xff08;AI&#xff09;正迅速崛起&#xff0c;成为推动企业创新和变革的关键力量。面对日益复杂的市场环境和激烈的行业竞争&#xff0c;企业亟需借助技术手段提高运营效率、优化决策过程&#xff0c;并增强市场竞争力。而AI…