【Spring】5.Spring事务中的@Transactional注解剖析

事务是确保数据完整性的关键机制。Spring框架通过@Transactional注解提供了一种声明式事务管理的方式,极大地简化了事务的使用。在本篇文章中,我们将深入探讨Spring的@Transactional注解,包括它的工作原理、可用属性、如何配置以及在嵌套事务场景下的应用。此外,我们还将讨论将@Transactional注解应用于类与方法时的异同,以及如何选择适当的使用方式。

Spring的@Transactional注解

Spring的@Transactional是一个用于声明方法或类级别的事务属性的注解。它告诉Spring框架,被注解的方法应该在一个事务的上下文中执行。如果方法在事务中执行,那么该方法对数据库所做的更改要么全部成功提交,要么在发生异常时全部撤销。

工作原理

  1. 代理机制:Spring使用AOP(面向切面编程)来实现@Transactional注解。当Spring容器启动时,它扫描所有的@Transactional注解,并为被注解的方法创建一个代理。对于类级别的注解,类中的所有方法都会创建代理。

  2. 事务的创建和结束:当代理方法被调用时,Spring首先检查是否存在一个活动的事务。如果存在,代理方法会加入到这个事务中。如果不存在,Spring会创建一个新的事务。一旦方法执行完成,如果没有异常抛出,事务将被提交;如果发生异常,事务将被回滚。

  3. 事务管理器:Spring使用事务管理器(如DataSourceTransactionManagerJpaTransactionManager)来实际控制事务的创建、提交和回滚。

属性及配置

  1. propagation:定义事务的传播行为。

    • REQUIRED:默认值,加入已存在的事务或创建新事务。
    • SUPPORTS:支持事务但不是必须的;如果没有事务,就以非事务方式执行。
    • MANDATORY:必须在一个事务中执行,否则抛出异常。
    • REQUIRES_NEW:总是创建新事务,并将任何存在的事务挂起。
    • NOT_SUPPORTED:以非事务方式执行,任何存在的事务都会被挂起。
    • NEVER:必须不在事务中执行,如果存在事务则抛出异常。
    • NESTED:如果支持,则创建一个嵌套事务。
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    
  2. isolation:定义事务的隔离级别。

    • DEFAULT:使用后端数据库的默认隔离级别。
    • READ_UNCOMMITTED:最低隔离级别,允许读取未提交的数据。
    • READ_COMMITTED:保证读取已提交的数据。
    • REPEATABLE_READ:保证在一个事务中看到的数据保持不变。
    • SERIALIZABLE:最高隔离级别,完全串行化的事务。
    @Transactional(isolation = Isolation.READ_COMMITTED)
    
  3. timeout:定义事务的超时时间(秒)。如果事务在这个时间内没有完成,它将被自动回滚。

    @Transactional(timeout = 30)
    
  4. readOnly:指定事务是否为只读事务。这可以给数据库一个优化的提示。

    @Transactional(readOnly = true)
    
  5. rollbackFor:定义哪些异常类型会导致事务回滚。可以指定一个异常类型数组。

    @Transactional(rollbackFor = {RuntimeException.class, CustomException.class})
    
  6. noRollbackFor:定义哪些异常类型不会导致事务回滚。可以指定一个异常类型数组。

    @Transactional(noRollbackFor = NoRollbackException.class)
    
  7. phase:定义在事务的哪个阶段应用事务管理。通常与基于方法的事务管理相关。

    @Transactional(phase = TransactionPhase.BEFORE_COMMIT)
    
  8. transactionManager:指定使用的事务管理器的Bean名称。

    @Transactional(transactionManager = "transactionManagerBeanName")
    

通过合理配置这些属性,可以精确控制事务的行为,满足业务需求。

处理嵌套事务

嵌套事务通常在以下情况下需要进行处理:

  1. 细粒度控制:当您希望在一个大的事务中包含一些小的事务,并且这些小的事务可以独立于大事务进行回滚或提交时。
  2. 复杂业务逻辑:在一些复杂的业务逻辑中,可能需要在一个事务中执行多个步骤,其中某些步骤需要独立的事务控制。
  3. 性能优化:在某些情况下,使用嵌套事务可以减少锁争用,从而提高性能。

在Spring Boot中,处理嵌套事务需要使用支持嵌套事务的事务管理器。由于Spring Boot默认的DataSourceTransactionManager不支持嵌套事务,因此通常需要使用JTA事务管理器,如AtomikosBitronix

以下是在Spring Boot中使用@Transactional注解处理嵌套事务的步骤和示例代码:

1. 添加JTA事务管理器依赖

首先,需要添加JTA事务管理器的依赖。以Atomikos为例:

<!-- pom.xml -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>

2. 配置JTA事务管理器

application.propertiesapplication.yml中配置JTA事务管理器:

# application.properties
spring.jta.enabled=true
spring.jta.log-dir=path/to/log/dir

3. 使用@Transactional注解处理嵌套事务

在服务层中,使用@Transactional注解声明外部事务和嵌套事务:

@Service
public class BusinessService {

    @Autowired
    private NestedService nestedService;

    @Transactional
    public void performBusinessOperation() {
        // 执行一些操作
        nestedService.performNestedOperation();
    }
}

@Service
public class NestedService {

    @Transactional(propagation = Propagation.NESTED, readOnly = true)
    public void performNestedOperation() {
        // 执行一些只读操作,这些操作在一个嵌套事务中
    }

    @Transactional(propagation = Propagation.NESTED, readOnly = false)
    public void performNestedOperationWithChange() {
        // 执行一些需要更改数据库的操作
        // 这些操作在一个嵌套事务中
    }
}

在这个例子中,BusinessService中的performBusinessOperation方法定义了一个外部事务。当调用NestedService中的performNestedOperationperformNestedOperationWithChange方法时,它们作为一个嵌套事务执行,因为它们也被@Transactional注解,且propagation属性设置为NESTED

注意事项:

  • 确保你的数据库和事务管理器都支持嵌套事务。
  • 使用嵌套事务可能会使事务管理逻辑变得复杂,因此应该谨慎使用。
  • 在使用JTA事务管理器时,可能需要对数据源进行额外的配置,以确保它们能够与JTA事务管理器协同工作。

@Transactional用于类或方法异同

在Spring框架中,@Transactional 注解可以用于类或方法,它们在事务管理上有不同的作用范围和含义:

类级别的 @Transactional

  • @Transactional 注解应用于整个类时,类中的所有公共方法都会继承这个注解的事务属性。
  • 这意味着,除非在单个方法上指定了不同的事务属性,否则类中所有公共方法都会按照类级别注解定义的事务属性执行。
  • 类级别的事务定义提供了一种方便的方式,当一个类中的多个方法共享相同的事务需求时,可以避免在每个方法上重复使用注解。
@Transactional(readOnly = true)
public class MyService {
    public void methodOne() {
        // ...
    }

    public void methodTwo() {
        // ...
    }
}

在这个例子中,MyService 类的 methodOnemethodTwo 都将以只读事务执行。

方法级别的 @Transactional

  • 方法级别的@Transactional 注解允许你对单个方法进行特定的事务配置,这会覆盖类级别的定义。
  • 这在需要对类中不同方法应用不同事务属性时非常有用。
  • 方法级别的注解提供了更细粒度的事务控制。
public class MyService {
    @Transactional(readOnly = true)
    public void readOnlyMethod() {
        // ...
    }

    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    public void writeMethod() {
        // ...
    }
}

在这个例子中,readOnlyMethod 将作为一个只读事务执行,而 writeMethod 将作为一个全新的写事务执行,即使 MyService 类上有类级别的@Transactional注解。

区别和使用场景:

  • 作用范围:类级别的注解影响该类的所有公共方法,而方法级别的注解只影响单个方法。
  • 事务属性:方法级别的注解可以覆盖类级别的注解定义的事务属性。
  • 使用场景:当你需要为类中的多个方法定义统一的事务行为时,可以使用类级别的注解。当你需要为类中的特定方法定义不同的事务行为时,应使用方法级别的注解。

选择使用类级别还是方法级别的@Transactional注解,应基于你的具体需求和事务管理策略。通常,如果多个方法共享相同的事务配置,类级别的注解会更加方便;而当需要对单个方法进行特殊处理时,方法级别的注解则更加灵活。

总结

在本文中,全面介绍了Spring框架中的@Transactional注解,它是实现声明式事务管理的核心工具。该注解能够自动为方法创建事务代理,通过定义不同的事务属性如传播行为、隔离级别、超时时间等,来精确控制事务的开始、提交或回滚。
特别地,讨论了嵌套事务的概念,它允许在现有事务中创建新的事务,这在处理复杂业务逻辑时非常有用。
此外,我们区分了将@Transactional注解应用于类与方法的不同影响,类级别的注解为所有公共方法提供了统一的事务语义,而方法级别的注解则允许更细粒度的事务控制。最后,我们强调了在使用嵌套事务和@Transactional注解时应注意的一些关键点,包括确保事务管理器和数据库的支持,以及对事务配置的谨慎选择。通过这些深入的讨论,我们希望帮助开发者更好地利用Spring的事务管理功能,以提升应用程序的数据处理能力和事务安全性。

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

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

相关文章

【MATLAB】GUI初步设计

MATLAB界面设计 前言一、基本步骤1.1 创建GUI文件1.2 界面设计 总结 前言 为了完成图像处理的作业&#xff0c;简直就是生活不易啊 找到一个很棒的教学视频 基于MATLAB的GUI界面设计流程讲解 一、基本步骤 1.1 创建GUI文件 由于在写博文之前我已经创建好文件了&#xff0c;…

邊緣智能2024—AI開發者峰會(5月9日)數碼港即將啟幕

隨著 AI &#xff08;人工智能&#xff09;技術的飛速發展&#xff0c;我們正迎來邊緣計算智能化與分布式AI深度融合的新時代&#xff0c;共同演繹分布式智能創新應用的壯麗篇章。"邊緣智能2024 - AI開發者峰會"將聚焦於這一前沿領域&#xff0c;探討如何通過邊緣計算…

中国发布首个汽车大模型标准

&#x1f989; AI新闻 &#x1f680; 中国发布首个汽车大模型标准 摘要&#xff1a;中国信息通信研究院于4月28日发布了国内首个汽车大模型标准&#xff0c;标志着汽车行业正式迈向“人工智能&#xff0b;”时代。该标准包含三个核心能力域&#xff1a;场景丰富度、能力支持度…

Pytorch学习笔记——环境配置安装

1、下载和配置环境 Anacodna必备&#xff08;工具包里面都包含的有&#xff0c;集成与运用科学分析的软件&#xff0c;比较方便&#xff09; 点击这个网页:Download Now | Anacondahttps://www.anaconda.com/download/success 按照教程安装&#xff08;教程可以自己在网上搜…

XY_RE复现(五)

一&#xff0c;给阿姨倒一杯卡布奇诺 是一道魔改TEA加密 给出了一些初始化&#xff0c;然后输入的flag拆分&#xff0c;两两一组&#xff0c;通过for循环放入encrypt加密函数 #include <stdio.h> #define uint32_t unsigned intvoid decrypt(uint32_t *v, uint32_t *ke…

拆单算法交易(Algorithmic Trading)

TWAP TWAP交易时间加权平均价格Time Weighted Average Price 模型&#xff0c;是把一个母单的数量平均地分配到一个交易时段上。该模型将交易时间进行均匀分割&#xff0c;并在每个分割节点上将拆分的订单进行提交。例如&#xff0c;可以将某个交易日的交易时间平均分为N 段&am…

守护数据安全: 零信任视角下的勒索病毒防范之道

前言 就在近日&#xff0c;鸿海集团旗下半导体设备大厂——京鼎精密科技股份有限公司&#xff08;以下简称“京鼎”&#xff09;遭到了黑客的入侵。黑客在京鼎官网公布信息直接威胁京鼎客户与员工&#xff0c;如果京鼎不支付赎金&#xff0c;客户资料将会被公开&#xff0c;员…

pyqt 滑动条控件QSlider

pyqt 滑动条控件QSlider 滑动条控件QSlider效果代码 滑动条控件QSlider QSlider 是 PyQt中的一个控件&#xff0c;它允许用户通过拖动滑块或点击滑块轨道上的任意位置来选择一系列值。 QSlider 有两种主要的类型&#xff1a;Qt.Horizontal&#xff08;水平滑块&#xff09;和 …

java版数据结构:深入理解栈和队列:数据结构与应用(vector,stack,queue)

目录 前言 动态数组类&#xff08;vector&#xff09; 特点&#xff1a; 应用&#xff1a; 栈&#xff08;Stack&#xff09; 栈的基础概念&#xff1a; 栈的常用方法&#xff1a; 模拟栈操作&#xff1a; 队列&#xff08;Queue&#xff09; 队列的基础概念 队列的常…

VS Code工具将json数据格式化

诉求&#xff1a;json数据格式化应该在工作中用到的地方特别多&#xff0c;为了更方便、更仔细的对json数据查看&#xff0c;将json数据格式化是非常有必要的。 VS Code中如何将json数据快速格式化 1、在VS Code中安装Beautify JSON插件 2、安装完后在需要格式化的文件中按住…

Easy TCP Analysis上线案例库功能,为用户提供一个TCP抓包分析案例分享学习的平台

​案例库&#xff0c;提供给用户相互分享TCP抓包故障排查案例或是经典学习案例的功能&#xff0c;任何用户都可从案例库查看其它用户分享的案例&#xff0c;每个用户也都可以上传自己的案例&#xff0c;经过平台审核去重即可展示在案例库。 对于学习&#xff0c;最典型的三次握…

Linux进程概念(下)

Linux进程概念 1. 命令行参数2. 环境变量2.1 环境变量的概念2.2 环境变量的使用和一些问题2.3 获取环境变量2.4 深入理解环境变量2.5 环境变量相关的命令 3. 进程地址空间3.1 基本概念3.2 为什么要有地址空间 1. 命令行参数 main函数也可以带参数的&#xff0c;如下 #include…

Linux内核之原子操作:atomic_long_dec用法实例(六十七)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

2023-2024年汽车行业报告/方案合集(精选345份)

汽车行业报告/方案&#xff08;精选345份&#xff09; 2023-2024年 来源&#xff1a;2023-2024年汽车行业报告/方案合集&#xff08;精选345份&#xff09; 【以下是资料目录】 2023中国汽车科技50强 2023中国智能汽车产业发展与展望 2023比亚迪海豹汽车拆解报告 2023新能…

PotatoPie 4.0 实验教程(31) —— FPGA实现摄像头图像高斯滤波

什么是高斯滤波 高斯滤波是一种常见的图像处理技术&#xff0c;用于去除图像中的噪声和平滑图像。它的原理基于统计学中的高斯分布&#xff08;也称为正态分布&#xff09;。 在高斯滤波中&#xff0c;一个二维的高斯核函数被用来对图像中的每个像素进行加权平均。这个高斯核…

【沉淀之华】从0到1实现用户推荐 - 实时特征系统构建,包含特征计算,特征存储,特征查询,特征补偿超详细思路分享

文章目录 背景介绍设计初衷基本概念 技术架构"四高"特征存储特征计算特征查询特征补偿 技术难点Q&A彩蛋 背景介绍 设计初衷 作为用户推荐系统的支撑系统之一&#xff1a;用户实时特征系统有着举足轻重的重要&#xff0c;甚至说它是一起推荐行为触发的必要条件。…

【经典算法】LeetCode 160. 相交链表(Java/C/Python3/Go实现含注释说明,Easy)

目录 题目描述思路及实现方式一&#xff1a;哈希表思路代码实现Java版本C语言版本Python3版本Golang版本 复杂度分析 方式二&#xff1a;双指针思路代码实现Java版本C语言版本Python3版本Golang版本 复杂度分析 总结相似题目 标签(题目类型)&#xff1a;链表 题目描述 给你两…

C语言——操作符保姆级教学(含整形提升及算数转换)

操作符 一.操作符的分类二.原码、反码、补码三.移位操作符1.左移操作符&#xff1a;<<2.右移操作符&#xff1a;>> 四.位操作符1.按位与—— &2.按位或—— |3.按位异或—— ^4.按位取反—— ~ 五.逗号表达式六.条件操作符七.操作符的属性&#xff1a;优先级、…

如何配置和使用Apollo的component里的plugin

关于如何使用Apollo的Component里的plugin&#xff0c;在Apollo的文档里只有如果和开发的说明却没有找到一个清楚完整说明怎么把plugin跑起来的说明&#xff0c;例如我想把lidar_detection_filter按我们的需求对目标过滤算法作修改然后编译完后&#xff0c;执行 cyber_launch …

【数据结构】链表专题3

前言 本篇博客我们继续来讨论链表专题&#xff0c;今天的链表算法题是经典中的经典 &#x1f493; 个人主页&#xff1a;小张同学zkf ⏩ 文章专栏&#xff1a;数据结构 若有问题 评论区见&#x1f4dd; &#x1f389;欢迎大家点赞&#x1f44d;收藏⭐文章 目录 1.判断链表是否…
最新文章