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

目录

(一)REQUIRED

(二)SUPPORTS

(三)MANDATORY

(四)REQUIRES_NEW

(五)NOT_SUPPORTED

(六)NEVER

(七)NESTED


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

(一)REQUIRED

  1. 定义:如果当前存在事务,就加入该事务;如果当前没有事务,就创建一个新的事务。这是最常见的选择,也是 Spring 的默认传播行为。
  2. 使用场景示例:在一个电商系统中,用户下单操作涉及订单创建、库存扣除和支付记录等多个步骤。这些步骤需要在同一个事务中完成,以确保数据的一致性。如果在某个步骤出现异常,整个事务应该回滚。此时,可以使用 REQUIRED 传播行为来保证这些操作在同一个事务中执行。例如:
@Service
public class OrderService {
    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private 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 {
    @Autowired
    private 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 {
    @Autowired
    private 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 {
    @Autowired
    private 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 {
    @Autowired
    private 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 {
    @Autowired
    private CacheManager cacheManager;

    @Transactional(propagation = Propagation.NEVER)
    public void loadCache() {
        // 从外部数据源加载数据到缓存中的逻辑
    }
}

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

(七)NESTED

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

    @Transactional(propagation = Propagation.NESTED)
    public void performSubOperation(Long subModuleId) {
        SubModule subModule = subModuleRepository.findById(subModuleId);
        // 进行子模块相关的操作逻辑
    }
}

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

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…

2024国游销量前20游戏分析:某开放世界武侠(排名11)

1、销量约20万套&#xff0c;销售额1400万人民币。 与一代的发售间隔为三年。 虽然对于网游大厂来说这个数字不够看&#xff0c;但对一个小团队来说足够维持了&#xff0c;三年的运营成本不是小数目。 2、开发商属于国内最早做3DMMO的厂商之一&#xff0c;创始人曾在国外大学…

没有公网IP实现seafile本地IP访问和虚拟局域网IP同时访问和上传文件

前言 Ubuntu 24.04 LTSDocker 安装 seafileOpenWrtTailscale Ubuntu 24.04 LTS 通过 docker desktop 安装 seafile 搭建个人网盘中&#xff0c;已经实现了本地局域网放问Ubuntu IP来访问Seafile&#xff0c;以及通过 Ubuntu 的 Tailscale IP 访问Seafile。但是&#xff0c;文…

大有国科举办书苑华夏文化读书会第四届文学艺术沙龙活动

经过了精心准备&#xff0c;2025年元月5日大有国科产业运营管理&#xff08;北京&#xff09;有限公司在北京西山赢府国际商务中心举办第四届文学艺术沙龙活动。大有数字集团董事长张长江,我国第一代电视艺术工作者悦怀怡,中华社会文化发展基金会原理事、副秘书长肖清波&#x…

JavaScript笔记进阶篇01——作用域、箭头函数、解构赋值

黑马程序员视频地址&#xff1a; 黑马程序员前端JavaScript入门到精通全套视频教程https://www.bilibili.com/video/BV1Y84y1L7Nn?vd_source0a2d366696f87e241adc64419bf12cab&spm_id_from333.788.videopod.episodes&p152 目录 作用域 局部作用域 函数作用域 块…

开源鸿蒙开发者社区记录

lava鸿蒙社区可提问 Laval社区 开源鸿蒙项目 OpenHarmony 开源鸿蒙开发者论坛 OpenHarmony 开源鸿蒙开发者论坛

蓝桥杯不熟知识整理

第一章 1.using namespace std; using namespace std; 是⼀种简单粗暴的做法&#xff0c;直接这样使⽤&#xff0c;就意味着后续在 std 这个名字空间中的各种定义都可以直接使⽤&#xff0c;但是我们往往只是使⽤部分。所以名字空间其实也 可以这样使⽤&#xff1a;std::cout…

机器学习(3):逻辑回归

1 介绍 逻辑回归&#xff08;Logistic Regression&#xff09;是一种广泛应用于分类问题的监督学习算法。尽管名字中含有“回归”二字&#xff0c;但这并不意味着它用于解决回归问题。相反&#xff0c;逻辑回归专注于解决二元或多元分类问题&#xff0c;如邮件是垃圾邮件还是非…

基于Python django的音乐用户偏好分析及可视化系统设计与实现

1.1 论文背景 随着信息技术的快速发展&#xff0c;在线音乐服务已成为日常生活的重要组成部分。QQ音乐&#xff0c;凭借其创新的音乐推荐算法和独特的社交特性&#xff0c;成功在竞争激烈的市场中获得一席之地。该平台的歌单文化和评论文化不仅满足了用户自尊和自我实现的需求…

蓝桥杯单片机第六届省赛

前言 这套题其实一开始做的时候有点发懵&#xff0c;一直陷入到一个巨大的漏洞里面&#xff0c;主要是在10次数据采集上面&#xff0c;说白了就是练得少&#xff0c;太菜了 题目 这套题到现在的代码也有一些漏洞&#xff0c;实在是不想改了&#xff0c;最近有点摆烂&#xff…

用java配合redis 在springboot上实现令牌桶算法

令牌桶算法配合 Redis 在 Java 中的应用令牌桶算法是一种常用的限流算法&#xff0c;适用于控制请求的频率&#xff0c;防止系统过载。结合 Redis 使用可以实现高效的分布式限流。 一.、引入依赖首先&#xff0c;需要在 pom.xml 文件中引入 spring-boot-starter-data-re…

Python绘制简易动态圣诞树

代码&#xff1a; import random import time from math import pi, cos, sin from tkinter import *CANVAS_WIDTH 640 # 画布的宽 CANVAS_HEIGHT 640 # 画布的高 TREE_COLOR "#2e8b57" # 树的颜色 TRUNK_COLOR "#8b4513" # 树干的颜色 STAR_COLO…

【HF设计模式】06-命令模式

声明&#xff1a;仅为个人学习总结&#xff0c;还请批判性查看&#xff0c;如有不同观点&#xff0c;欢迎交流。 摘要 《Head First设计模式》第6章笔记&#xff1a;结合示例应用和代码&#xff0c;介绍命令模式&#xff0c;包括遇到的问题、采用的解决方案、遵循的 OO 原则、…

高并发内存池_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…

消息队列篇--原理篇--Pulsar(Namespace,BookKeeper,类似Kafka甚至更好的消息队列)

Apache Pulusar是一个分布式、多租户、高性能的发布/订阅&#xff08;Pub/Sub&#xff09;消息系统&#xff0c;最初由Yahoo开发并开源。它结合了Kafka和传统消息队列的优点&#xff0c;提供高吞吐量、低延迟、强一致性和可扩展的消息传递能力&#xff0c;适用于大规模分布式系…

音频入门(二):音频数据增强

本文介绍了一些常见的音频数据增强方法&#xff0c;并给出了代码实现。 目录 一、简介 二、代码 1. 安装必要的库 2. 代码 3. 各函数的介绍 4. 使用方法 参考&#xff1a; 一、简介 音频数据增强是机器学习和深度学习领域中用于改善模型性能和泛化能力的技术。 使用数据…

Oracle审计

审计是监控选定的用户数据库操作的过程 审计的目的&#xff1a; 调查可疑的数据库活动&#xff1a; 审计可以帮助检测和跟踪潜在的 security breaches、未授权的访问尝试或其他异常行为。通过分析审计日志&#xff0c;可以确定可疑活动的来源、时间、频率和影响。 收集特定数…

Appium(四)

一、app页面元素定位 1、通过id定位元素: resrouce-id2、通过ClassName定位&#xff1a;classname3、通过AccessibilityId定位&#xff1a;content-desc4、通过AndroidUiAutomator定位5、通过xpath定位xpath、id、class、accessibility id、android uiautomatorUI AutomatorUI自…

AUTOSAR OS模块详解(三) Alarm

AUTOSAR OS模块详解(三) Alarm 本文主要介绍AUTOSAR OS的Alarm&#xff0c;并对基于英飞凌Aurix TC3XX系列芯片的Vector Microsar代码和配置进行部分讲解。 文章目录 AUTOSAR OS模块详解(三) Alarm1 简介2 功能介绍2.1 触发原理2.2 工作类型2.3 Alarm启动方式2.4 Alarm配置2.5…

【0x04】HCI_Connection_Request事件详解

目录 一、事件概述 二、事件格式及参数 2.1. HCI_Connection_Request 事件格式 2.2. BD_ADDR 2.3. Class_Of_Device 2.4. Link_Type 三、主机响应 3.1. ACL链接类型 3.2. SCO或eSCO链接类型 四、应用场景 4.1. 设备配对场景 4.2. 蓝牙文件传输场景 4.3. 蓝牙物联网…