Spring 事务的使用、隔离级别、@Transactional的使用

news2024/10/7 12:21:05


        Spring事务是Spring框架提供的一种机制,用于管理应用程序中的数据库事务。

        事务是一组数据库操作的执行单元,要么全部成功提交,要么全部失败回滚,保证数据的一致性和完整性。

Spring事务提供了声明式事务和编程式事务两种方式:

  1. 编程式事务: 编程式事务是通过编写代码来手动管理事务的开始、提交或回滚,开发人员需要显式地调用事务管理器的方法来控制事务的边界。

  2. 声明式事务: 声明式事务是通过在配置文件或注解中声明事务的属性来实现的。开发人员只需要关注业务逻辑,而不需要关心事务的管理。Spring框架会根据注解的配置自动管理事务的开始、提交或回滚。


1. 编程式事务:

        在Spring编程式事务中,DataSourceTransactionManager和TransactionDefinition是两个核心的类:

  1. DataSourceTransactionManager: 它是基于数据源(DataSource)的事务管理器,通过获取连接并控制连接的提交或回滚来管理事务。使用时,需要配置一个数据源(DataSource),用于获取数据库连接。在事务开始时,它会从数据源中获取一个数据库连接,并将该连接绑定到当前线程上下文中。在事务结束时,它会根据事务的提交或回滚状态,来决定是否提交或回滚数据库连接。

  2. TransactionDefinition: 是Spring框架定义的事务属性接口,用于定义事务的一些属性,比如事务的隔离级别、传播行为、超时时间等。

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @Autowired
    private DataSourceTransactionManager transactionManager;
    @Autowired
    private TransactionDefinition transactionDefinition;

    @RequestMapping("/del")
    public int del(Integer id) {
        if (id != null && id > 0) {
            // 开启事务
            TransactionStatus transactionStatus = null;
            // 业务操作,进行删除
            int result = 0;
            try {
                transactionStatus = transactionManager.getTransaction(transactionDefinition);
                result = userService.del(id);
                System.out.println("删除成功:" + result);
                transactionManager.commit(transactionStatus); // 提交
            } catch (Exception e) {
                if (transactionStatus != null) {
                    transactionManager.rollback(transactionStatus); // 回滚
                }
            }
            return result;
        }
        return 0;
    }
}

2. 声明式事务:

        编程式事务写起来较麻烦,声明式事务用起来较方便。

        声明式事务可以通过使用 @Transactional 注解来实现:

        当方法执行完成后,如果没有发生异常,事务管理器会自动提交事务;如果发生异常,事务管理器会自动回滚事务。也可以通过在方法上抛出异常手动来触发事务的回滚。

@RestController
@RequestMapping("/user2")
public class UserController2 {
    @Autowired
    private UserService userService;

    @Transactional
    @RequestMapping("del")
    public int del(Integer id) {
        if (id == null || id < 0) return 0;
        int ret = userService.del(id);
        System.out.println("删除:" + id);
        return ret;
    }
}

3. @Transactional 注解的具体使用:

3.1 作用范围: 

@Transactional注解支持修饰方法,也可以修饰类:

  • 修饰方法时:需要注意只能应用到 public 方法上,否则不生效。推荐此种用法。

  •  修饰类时:表明该注解对该类中所有的 public 方法都生效。

3.2 支持参数设置:

这些参数可以根据实际需求进行设置,如果不指定参数,则使用默认值。

  1. value:指定使用的事务管理器的名称。可以通过名称引用已经配置的事务管理器。默认值为空,表示使用默认的事务管理器。

  2. propagation:指定事务的传播行为。可以设置为以下值之一:

    • REQUIRED:如果当前没有事务,则创建一个新的事务;如果当前存在事务,则加入到当前事务中。
    • REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则将当前事务挂起。
    • NESTED:在当前事务的嵌套事务中执行。如果当前没有事务,则创建一个新的事务。
    • SUPPORTS:如果当前存在事务,则加入到当前事务中;如果当前没有事务,则以非事务方式执行。
    • MANDATORY:如果当前存在事务,则加入到当前事务中;如果当前没有事务,则抛出异常。
    • NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
    • NOT_SUPPORTED:以非事务方式执行,如果当前存在事务,则将当前事务挂起。
  3. isolation:指定事务的隔离级别。可以设置为以下值之一:

    • DEFAULT:使用默认的隔离级别(以连接的数据库隔离级别为准)。
    • READ_UNCOMMITTED:允许读取未提交的数据。
    • READ_COMMITTED:只能读取已提交的数据。
    • REPEATABLE_READ:保证可重复读取,禁止脏读和不可重复读。
    • SERIALIZABLE:保证可串行化的隔离级别,禁止脏读、不可重复读和幻读。
  4. timeout:指定事务的超时时间,单位为秒。如果事务在指定的时间内没有完成,则会被自动回滚。默认值为-1,表示没有超时限制。

  5. readOnly:指定事务是否为只读事务。如果设置为true,则表示只读事务,不允许进行任何修改操作。默认值为false。

  6. rollbackFor:指定哪些异常触发事务的回滚。可以设置为一个异常类或异常类数组。默认情况下,只有运行时异常和Error会触发事务的回滚。

  7. noRollbackFor:指定哪些异常不触发事务的回滚。可以设置为一个异常类或异常类数组。默认情况下,运行时异常和Error会触发事务的回滚。

如图: 如果要加多个参数,可以使用逗号隔开

 

使用注意事项:未检测到异常不回滚

使用 @Transactional 注解是它检测到异常才会回滚,但如果在代码中,使用 try-catch 检测到异常,并在这时程序终止了,那么事务就不会被回滚,这时非常可怕的事情。

例如:

 

解决方案1:从原因入手

        既然是 @Transactional 没有检测到异常,那我们让它检测而到就可以了,所以可以在 catch 中将异常抛出,让 @Transactional 能检测到即可

 

解决方案2:从结果入手

        在 catch 中借助 TransactionAspectSupport 的相关方法来手动回滚事务

3.3 经典面试题:

(1)@Transactional 的工作原理?

@Transactional是Spring框架中用于实现声明式事务管理的注解。它的工作原理是基于AOP(Aspect-Oriented Programming)技术。

  1. 当Spring容器启动时,会扫描所有被@Transactional注解标注的类和方法。

  2. 当调用被@Transactional注解标注的方法时,Spring会通过AOP技术在方法执行前后织入事务管理的逻辑。

  3. 在方法执行前,事务管理器会开启一个新的事务。

  4. 在方法执行过程中,如果发生异常,事务管理器会回滚事务,即撤销之前的操作。

  5. 如果方法执行成功,事务管理器会提交事务,即将之前的操作永久保存到数据库中。

  6. 如果方法执行过程中调用了其他被@Transactional注解标注的方法,事务管理器会根据事务的传播行为来决定是否将这些方法加入到当前事务中。

        需要注意的是,声明式事务只适用于公共方法,即在Spring容器中被代理的方法。如果在同一个类中的非公共方法中调用了带有@Transactional注解的公共方法,事务将不会生效。这是因为Spring使用AOP技术来实现声明式事务,只能拦截公共方法的调用。

(2)Spring 事务失效有哪些原因?

Spring事务失效的原因有以下几种可能:

1. 未正确配置事务管理器:在Spring中,需要配置事务管理器(例如DataSourceTransactionManager)来管理事务。如果未正确配置事务管理器,或者配置有误,可能导致事务失效。

2. 事务注解未生效:使用@Transactional注解来声明事务,但是注解未被正确识别和解析。可能是因为未在配置文件中启用事务注解的解析,或者注解所在的类未被Spring容器扫描到。

3. 异常未被正确抛出:事务的回滚是基于异常的,默认情况下,只有运行时异常和Error会触发事务的回滚。如果在事务方法中捕获了异常并未重新抛出,或者捕获的异常类型不符合回滚条件,事务将不会回滚。

4. 事务传播行为设置不正确:事务的传播行为决定了事务方法与其他事务方法的关系。如果事务方法的传播行为设置不正确,可能导致事务失效或不符合预期。

5. 方法未被代理:声明式事务是通过AOP技术实现的,只有被Spring容器管理的Bean中的方法才会被代理,从而实现事务的管理。如果方法未被代理,事务将不会生效。

6. 数据库不支持事务:某些数据库可能不支持事务,或者事务的隔离级别不被支持。在这种情况下,无法实现事务的管理。

7. 方法被重载:如果一个类中存在多个同名方法,但参数列表不同,而只有其中一个方法被@Transactional注解标注,那么其他同名方法的事务将不会生效。

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

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

相关文章

[Tools: Camera Conventions] NeRF中的相机矩阵估计

参考&#xff1a;NeRF代码解读-相机参数与坐标系变换 - 知乎 在NeRF中&#xff0c;一个重要的步骤是确定射线&#xff08;rays&#xff09;的初始点和方向。根据射线的初始点和方向&#xff0c;和设定射线深度和采样点数量&#xff0c;可以估计该射线成像的像素值。估计得到的…

Live Market:中国“一带一路”十周年,品牌出海跨境电商成为新引擎

​中国提出的“一带一路”倡议已经迎来10周年。高质量共建“数字丝绸之路”是这一倡议的重点方向&#xff0c;能够巩固互联互通合作基础、拓展国际合作新空间、扎牢风险防控网络&#xff0c;实现更高合作水平、更高投入效益、更高供给质量、更高发展韧性&#xff0c;推动共建“…

Python教程三:Python基本概念

1、Python基本语法 Python中严格区分大小写Python中每一行就是一条语句&#xff0c;每条语句以换行结束每一行语句不建议过长&#xff08;一般不建议超过80个字符&#xff09;一条语句可以多行编写&#xff0c;语句后加\结尾Python是缩进严格的语言&#xff0c;所以在Python中…

简单认识NoSQL的Redis配置与优化

文章目录 一、关系型数据库与非关系型数据库1、关系型数据库&#xff1a;2、非关系型数据库3、关系型数据库和非关系型数据库区别&#xff1a;4、非关系型数据库应用场景 二.Redis1、简介2、优点&#xff1a;3、Redis为什么这么快&#xff1f; 三、Redis 安装部署1、安装配置2、…

IDEA配置maven3.6.1时报错: 不支持发行版本 5 或 java: 不再支持源选项 5。请使用 7 或更高版本。

环境&#xff1a;Win10 IDEA 2022.3.3&#xff0c;JDK16&#xff0c;配置maven3.6.1 生成工程后&#xff0c;运行程序&#xff0c;结果报错如下&#xff1a; 不支持发行版本 5 好&#xff0c;此时更改以下选项&#xff1a; 此处我改为16&#xff0c;因为我的JDK是16版本的…

C#实现数字验证码

开发环境&#xff1a;VS2019&#xff0c;.NET Core 3.1&#xff0c;ASP.NET Core API 1、建立一个验证码控制器 新建两个方法Create和Check&#xff0c;Create用于创建验证码&#xff0c;Check用于验证它是否有效。 声明一个静态类变量存放列表&#xff0c;列表中存放包含令…

【论文阅读】定制化diffusion微调: DreamBooth原理

论文&#xff1a;DreamBooth: Fine Tuning Text-to-Image Diffusion Models for Subject-Driven Generation 项目&#xff1a;DreamBooth: Fine Tuning Text-to-Image Diffusion Models for Subject-Driven Generation 代码&#xff1a;Dreambooth-Stable-Diffusion 1. 任务简…

8. Spring Boot 日志文件

目录 1. 日志的作用 2. 如何使用日志 3. 自定义日志打印 3.1 获取日志对象 3.2 设置打印的内容 3.3 常见的日志框架 3.4 日志格式说明 4. 日志级别 4.1 日志级别的作用 4.2 日志级别的分类 4.3 日志级别的使用 4.4 设置日志级别 4.5 分目录设置日志级别 5. 日志…

达梦数据库-下载安装、基本操作及报错处理

下载安装 懒得记官网直接上网搜 产品下载-达梦数据 里面我是按图选择的Dm8 X86 Win64 下载完成后 解压 得到两个文件,打开上面这个ISO文件 打开安装包 setup.exe 这里默认选择中国时间 根据指示一步一步安装即可 选择刚刚安装的DM管理工具即可进入 基本操作 -- 获取所有…

SOLIDWORKS PDM只读文件的处理方法

如果用户检出一个文件&#xff0c;该文件在 SolidWorks 或其他应用程序中仍然以只读形式装入&#xff0c;最常见的原因包括&#xff1a; 1. 核实正在检出的文件尚未在现有 SolidWorks 进程中以只读方式打开。 这是一个常见错误&#xff0c;用户已经在 SolidWorks 打开了装配体…

MySQL界面客户端及高级的复杂查询

十五、MySQL界面客户端 十六、高级的复杂查询 1、查询去重 2、分组查询 gender和name没有同时相同的&#xff0c;相当于没分组 3、别名的使用 4、分组后的筛选 5、排序 6、分页 7、查询的顺序

Vue源码学习 - 异步更新队列 和 nextTick原理

目录 前言一、Vue异步更新队列二、nextTick 用法三、原理分析四、nextTick 源码解析1&#xff09;环境判断2&#xff09;nextTick() 五、补充 前言 在我们使用Vue的过程中&#xff0c;基本大部分的 watcher 更新都需要经过 异步更新 的处理。而 nextTick 则是异步更新的核心。…

【能量管理系统( EMS )】基于粒子群算法对光伏、蓄电池等分布式能源DG进行规模优化调度研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

基于量子同态加密的安全多方凸包协议

摘要安全多方计算几何(SMCG)是安全多方计算的一个分支。该协议是为SMCG中安全的多方凸包计算而设计的。首先&#xff0c;提出了一种基于量子同态加密的安全双方值比较协议。由于量子同态加密的性质&#xff0c;该协议可以很好地保护量子电路执行过程中数据的安全性和各方之间的…

分享一套功能齐全的免费开源MES系统

万界星空科技的开源MES功能&#xff1a; 1、基础数据管理&#xff1a; 2、质量管理&#xff1a; 质检项目维护&#xff0c;根据物料或者型号管理质检项目。检验页面&#xff0c;抽检确认。 3、工艺文件管理 &#xff1a;工艺参数&#xff0c;BOM文件&#xff0c;导入导出 报表&…

【树莓派入门】

一、镜像烧录 烧录器&#xff1a;Raspberry Pi Imager 下载链接&#xff1a;树莓派镜像烧录器下载 创建 ssh 文件 手动创建一个空白记事本.txt文件&#xff0c;命名为ssh&#xff0c;重命名&#xff0c;删掉.txt扩展名。将这个文件放入SD卡的boot盘中 wpa_supplicant.conf …

电流源电路

3.3.3电流源电路 镜像电流源 电路 分析 仿真 比例电流源 电路 分析 仿真 加射极输出器的电流源1 电路 分析 仿真 加射极输出器的电流源2 电路 分析 仿真 威尔逊电流源 电路 分析 仿真

Docker 全栈体系(八)

Docker 体系&#xff08;高级篇&#xff09; 六、Docker轻量级可视化工具Portainer 1. 是什么 Portainer 是一款轻量级的应用&#xff0c;它提供了图形化界面&#xff0c;用于方便地管理Docker环境&#xff0c;包括单机环境和集群环境。 2. 安装 官网 https://www.portain…

QTday3消息弹框/计时器

闹钟小软件 widget.cpp #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QDebug> #include <QPushButton> #include <QLabel> #include <QTimer> #include <QTimerEvent> #include <QTime> #include <QMessageB…

版本适配好帮手 Android SDK Upgrade Assistant / Android Studio Giraffe新功能

首先是新版本一顿下载↓&#xff1a; Download Android Studio & App Tools - Android Developers 在Tools中找到Android SDK Upgrade Assistant 可以在此直接查看SDK升级相关信息&#xff0c;不用跑到WEB端去查看了。 例如看一下之前经常要对老项目维护的android 12蓝牙…