【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 {@Autowiredprivate NestedService nestedService;@Transactionalpublic 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.mzph.cn/pingmian/5762.shtml

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

相关文章

再生龙clonezilla使用方法

目录 本文相关内容的介绍服务器窗口重定向引导进入再生龙系统检查本机操作系统的引导模式 再生龙基础功能选择选择 device-image选择ssh_server 网络配置ssh_server 配置ssh_server 镜像存储路径 再生龙抓取操作系统抓取镜像的命名 再生龙恢复操作系统拉取镜像的选择 本文相关内…

【Docker学习】docker checkpoint简单了解

docker checkpoint是一个试验性的功能&#xff0c;旨在用于测试和反馈&#xff0c;未来不确定是否会发生变化或是被删除掉&#xff0c;现有的功能我们可以简单了解了解。 docker checkpoint主要用于管理检查点&#xff08;CheckPoint&#xff09;。检查点&#xff08;CheckPoi…

【16-Ⅰ】Head First Java 学习笔记

HeadFirst Java 本人有C语言基础&#xff0c;通过阅读Java廖雪峰网站&#xff0c;简单速成了java&#xff0c;但对其中一些入门概念有所疏漏&#xff0c;阅读本书以弥补。 第一章 Java入门 第二章 面向对象 第三章 变量 第四章 方法操作实例变量 第五章 程序实战 第六章 Java…

收藏:关于闭包表

参考视频&#xff1a;【IT老齐513】经典树形数据结构-闭包表_哔哩哔哩_bilibili&#xff0c; 这个视频系列的确不错&#xff0c;500多个了。 闭包表&#xff0c;其实就是用来做树形结构的时候&#xff0c;如何快速找到某个节点下的所有后代节点&#xff0c;用两张表去完成&…

【html知识】用html写一个简单的个人网页

介绍&#xff1a; 这是一个HTML和CSS的代码段&#xff0c;它构建了一个基本的个人网页布局。以下是该代码的详细介绍&#xff1a; HTML部分&#xff1a; 文档类型与基础结构&#xff1a;<!DOCTYPE html> 声明了文档类型为HTML5。<html lang"en"> 定义…

设计模式-03 设计模式-依赖倒转原则案例分析

设计模式-03 设计模式-依赖倒转原则案例分析 目录 设计模式-02 设计模式-依赖倒转原则案例分析 1.定义 2.内涵 3.案例对比 4.注意事项 5.最佳实践 6.总结 1.定义 依赖倒转原则&#xff08;Dependency Inversion Principle&#xff0c;简称DIP&#xff09;高层级的模块…

ModuleNotFoundError: No module named ‘pyautogui‘

ModuleNotFoundError: No module named pyautogui 这个错误意味着你的Python环境中没有安装pyautogui这个模块。pyautogui是一个用于程序化地控制鼠标和键盘的Python模块&#xff0c;常常用于自动化任务、GUI测试等场景。 为了解决这个问题&#xff0c;你需要安装pyautogui模块…

Java实现以图识图功能模块(简单案例)

由于完整的以图识图系统代码较长且复杂&#xff0c;这里仅提供使用OpenCV进行特征提取和比较的简化版示例代码。 1. 引入OpenCV Java库 首先&#xff0c;你需要在项目中引入OpenCV的Java库。这通常涉及将OpenCV的jar包添加到项目的类路径中。 2. 提取图像特征 使用OpenCV的…

机器学习实战-聚类算法

聚类算法是一种无监督学习的算法&#xff0c;用于将数据集中的数据分成不同的聚类或组。聚类算法是数据挖掘和机器学习领域中常见的技术之一&#xff0c;具有广泛的应用。 以下是聚类算法的一些知识点&#xff1a; 聚类算法的目的是将数据集划分为不同的组&#xff0c;使得组内…

C++ 矩阵

目录 了解矩阵的数学原理&#xff08;大学线性代数&#xff09; 矩阵及转置矩阵 矩阵乘法 矩阵快速幂 相伴矩阵模板 [相伴矩阵,快速矩阵幂]CSES1722 Fibonacci Numbers 了解矩阵的数学原理&#xff08;大学线性代数&#xff09; 矩阵及转置矩阵 这里A就是一个矩阵&…

uniapp 桌面应用插件 Ba-Launcher

简介&#xff08;下载地址&#xff09; Ba-Launcher 可以让你的应用成为简单的桌面应用&#xff0c;如需扩展功能&#xff0c;请联系我。 截图展示 可关注博客&#xff0c;实时更新最新插件&#xff1a; uniapp 常用原生插件大全 使用方法 使用方法也很简单&#xff0c;在插…

PG数据库结构与oracle比较

1.数据库集簇逻辑结构 数据库集簇概念&#xff1a;一个大的数据库是由若干个小的数据库组成&#xff0c;实现数据的隔离存放&#xff0c;在概念上应该是与mysql一样的 在mysql中可以用show database列出数据库 PG中用\l 数据库对象存放在数据库中&#xff1a; PG中的所有数据…

题解:CF1951E(No Palindromes)

题解&#xff1a;CF1951E&#xff08;No Palindromes&#xff09; 题目翻译&#xff1a;给定一个长度为 n n n 的字符串 s s s&#xff0c;询问是否可以将其分成若干份&#xff0c;使得每一份都不是回文串。若可以&#xff0c;输出 YES 并给出任意一组方案&#xff1b;若不可…

【BASH 常用脚本系列3 -- shell实现查找目录并进入目录】

文章目录 shell实现查找目录并进入目录脚本实现shell实现查找目录并进入目录 在linux中终端下工作,如果要进入一个深度很深的目录的话需要 cd ./xx/xx./.. 执行很多次,用起来很麻烦,有些人就建议使用autojump来实现,但是autojump 的一个缺点是:如果本地有多套代码,只是它…

计算机英文论文常见错误写作习惯3

目录 第一部分 Numbers and Equations ‘such as’ and ‘etc.’ 第二部分 第一部分 Numbers and Equations 两个非常常见的错误是关于阿拉伯数字和方程式的表示。中国作家通常写阿拉伯数字&#xff0c;而不是拼出单词。然而&#xff0c;使用阿拉伯数字本身并不是一个错误…

【Shell】part1-Shell-基础入门篇

part1-基础入门 HelloWorld 创建,编写,运行 Shell 脚本 vim test.sh#!/bin/bash echo "Hello World !"# 1.作为可执行程序运行 chmod ax ./test.sh #使脚本具有执行权限 ./test.sh #执行脚本# 2.作为解释器参数运行 /bin/sh test.sh /bin/php test.php变量 变…

【Python】 逻辑回归:从训练到预测的完整案例

我把我唱给你听 把你纯真无邪的笑容给我吧 我们应该有快乐的 幸福的晴朗的时光 我把我唱给你听 用我炙热的感情感动你好吗 岁月是值得怀念的留恋的 害羞的红色脸庞 谁能够代替你呀 趁年轻尽情的爱吧 最最亲爱的人啊 路途遥远我们在一起吧 &#x1f3b5; 叶…

如何利用STM32F103实现太阳板的光线追踪

如何利用STM32F103实现太阳板的光线追踪 太阳能发电效率的提升一直是绿色能源领域的研究热点。通过太阳板的光线追踪技术&#xff0c;我们可以确保太阳板始终面向太阳&#xff0c;从而最大化其接收阳光的面积&#xff0c;提高能源转换效率。本文将介绍如何利用STM32F103微控制…

Redis第15讲——RedLock、Zookeeper及数据库实现分布式锁

由于篇幅原因&#xff0c;在上篇文章我们只介绍了redis实现分布式锁的两种方式——setnx和Redission&#xff0c;并对Reidssion加锁和看门狗机制的源码进行了分析&#xff0c;但这两种方案在极端情况下都会出现或多或少的问题。那么针对上述问题&#xff0c;比较主流的解决方案…

Linux服务器基本操作

Linux下服务器基本操作指令 Vim 文件名 进入 i编辑 esc退出编辑 &#xff1a;wq 保存退出 Cp -r文件夹 path 完整或…/ Cp 文件 path pwd 查看当前目录 rm -rf 2005 删除文件夹 Mkdir 创建文件夹 squeue查看提交队列 tail -f rsl.out.0000 在运行当前目录下查看进度 Scancel j…