SpringBoot事务处理

一、事务回顾

回顾地址:  深入理解数据库事务(超详细)_数据库事务操作_Maiko Star的博客-CSDN博客

 

事务: 是一组操作的集合,是一个不可分割的工作单位,这些操作要么同时成功,要么同时失败 

事务的操作

  • 开启事务(一组操作开始前,开启事务):start transaction / begin
  • 提交事务:(这组操作全部成功后,提交事务),commit
  • 回滚事务:(中间任何一个操作出现异常,回滚事务),rollback

SpringBoot中的事务是指一组操作数据库的动作集合,事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做。

二、SpringBoot事务的实现方式

(1)声明式事务管理(推荐)

        声明式事务管理建立在 AOP 之上,其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行目标方法之后根据执行的情况提交或者回滚事务。声明式事务管理不需要入侵代码,通过 @Transactional 就可以进行事务的操作,推荐使用。

  • 在方法上添加@Transactional注解,表示该方法需要被事务管理。
  • 使用Propagation属性指定事务的传播行为,默认是REQUIRED,即如果当前存在事务,则加入该事务,如果没有事务,则新建一个事务。
  • 使用Isolation属性指定事务的隔离级别,默认是数据库的默认隔离级别。
  • 使用readOnly属性指定事务是否为只读,如果为只读,则在事务中不允许进行写操作,默认为false
  • 使用rollbackFor属性指定哪些异常触发事务回滚,默认为RuntimeException

示例代码:

@Service
@Transactional
public class UserService {@Autowiredprivate UserRepository userRepository;public User createUser(User user) {// 业务逻辑return userRepository.save(user);}public void updateUser(User user) {// 业务逻辑userRepository.save(user);}
}

(2)编程式事务管理

        编程式事务管理使用 TransactionTemplate或者直接使用底层的 PlatformTransactionManager。对于编程式事务管理,spring 推荐使用 TransactionTemplate。

  • 使用TransactionTemplate手动控制事务的开始和提交/回滚。
  • execute方法内部执行需要被事务管理的业务逻辑。

示例代码:

@Service
public class UserService {@Autowiredprivate TransactionTemplate transactionTemplate;@Autowiredprivate UserRepository userRepository;public User createUser(User user) {return transactionTemplate.execute(status -> {try {// 业务逻辑return userRepository.save(user);} catch (Exception e) {status.setRollbackOnly();throw e;}});}public void updateUser(User user) {transactionTemplate.execute(status -> {try {// 业务逻辑userRepository.save(user);} catch (Exception e) {status.setRollbackOnly();throw e;}return null;});}
}

三、@Transactional 注解介绍及使用

3.1 @Transactional 作用范围

@Fransactional 可以用来修饰方法或类:

  • 修饰方法时:表示当前的方法开启事务,需要注意只能应用在 public 方法上。
  • 修饰类时:表示当前该类下面的所有被 public 修饰的方法都开启事务。
  • 默认会回滚运RuntimeException 及其子类

3.2 @Transactional 参数说明

参数作用
value当配置了多个事务管理器时,可以使用该属性指定选择哪个事务管理器。
transactionManager当配置了多个事务管理器时,可以使用该属性指定选择哪个事务管理器。
propagation事务的传播行为,默认值为 Propagation.REQUIRED。
isolation事务的隔离级别,默认值为 Isolation.DEFAULT。
timeout事务的超时时间,默认值为-1(表示没有超时时间)。如果超过该超时时间显示但事务还没有完成,则自动回滚事务。
readOnly指定事务是否为只读事务,默认值为 false。为了忽略那些不需要事务的方法,比如读取数据,可以设置为 true。
rollbackFor用于指定能够被触发事务回滚的异常类型,可以指定多个异常类型。
rollbackForClassName用于指定能够被触发事务回滚的异常类型,可以指定多个异常类型。
noRollbackFor抛出异常的类型,不回滚事务,也可以指定多个异常类型。
noRollbackForClassName抛出异常的类型,不回滚事务,也可以指定多个异常类型。

参数名称功能描述readOnly该属性用于设置当前事务是否为只读模式,设置为 true 表示只读,false 表示可读可写,默认情况下是 false。

例如: @Transactional(readOnly = true)rollbackFor该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。

例如:

指定单一异常类:@Transactional(rollbackFor = Exception.class)

指定多个异常类:@Transactional(rollbackFor ={RuntimeException.class,Exception.class})rollbackForClassName该属性用于设置需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,则进行事务回滚。

例如:

指定单一异常类名:@Transactional(rollbackForClassName = "RuntimeException")

指定多个异常类名:@Transactional(rollbackForClassName = {"RuntimeException","Exception"})noRollbackFor该属性用于设置不需要进行回滚的异常类数组。使用方法同 rollbackFornoRollbackForClassName该属性用于设置不需要进行回滚的异常类名称数组。使用方法同 rollbackForClassNamepropagation该属性用于设置事务的传播行为。isolation该属性用于设置事务的隔离级别。timeout该属性用于设置事务的超时秒数,默认值为 -1 表示永不超时。

3.3 @Transactional 出现异常注意事项

        1.@Transactional 只能放在 public 修饰的方法上。

        2.@Transactional,不加任何参数时,默认会回滚运RuntimeException 及其子类,其它范围之外的异常 Spring 不会帮我们去回滚数据。

        3.@Transactional(rollbackFor = Exception.class),如果加上rollbackFor 参数,会回滚所指定的异常类,前提下一定要在catch中抛出相关异常类,否则事务还是失效的。

        4.@Transactional 在异常被捕获的情况下,不会进行事务的自动回滚

 默认情况下,Spring 中的事务如果遇到运行时异常,事务是会进行回滚的,但遇到非运行时异常,事务不会自动回滚。可以设置 rollbackFor 来解决非运行时异常不会被回滚的问题。示例代码如下:

@RequestMapping("/test3")
@Transactional
public String test3(@RequestParam String username, @RequestParam String pwd) {// 插⼊数据库int result = userService.addUser(username, pwd);try {// 执⾏了异常代码int i = 10 / 0;} catch (Exception e) {}

以上代码虽然出现了算数异常,但是由于主动捕获了,且没有进行抛出,因此不会进行事物的回滚,数据库中会插入该条数据。

如果要解决出现异常事务不能自动回滚的问题,以下提供两种解决方案:

(1)方案一:对于捕获的异常,事务是不会自动回滚的,因此可以在捕获异常后主动将该异常重新抛出。默认只回滚RunTimeException,故我们这里演示抛出RunTimeException,示例代码如下:

@RequestMapping("/test3")
@Transactional
public String test3(@RequestParam String username, @RequestParam String pwd) {// 插⼊数据库int result = userService.addUser(username, pwd);try {// 执⾏了异常代码int i = 10 / 0;} catch (Exception e) {// 将异常重新抛出throw new RunTimeException();}return "测试完成!"; 
}

方案二(推荐):手动去回滚事务,可以通过方法 TransactionAspectSupport.currentTransactionStatus() 得到当前的事务,然后设置回滚方法 setRollbackOnly 就可以实现回滚。示例代码如下:

@RequestMapping("/test3")
@Transactional
public String test3(@RequestParam String username, @RequestParam String pwd) {// 插⼊数据库int result = userService.addUser(username, pwd);try {// 执⾏了异常代码int i = 10 / 0;} catch (Exception e) {// 手动回滚
TransactionStatus transactionStatus = TransactionAspectSupport.currentTransactionStatus();transactionStatus.setRollbackOnly();}return "测试完成!";
}

使用了TransactionAspectSupport类来获取当前的事务状态,并通过调用setRollbackOnly()方法手动回滚事务。这是Spring框架中一种手动回滚事务的方式。

3.4  @Transactional 失效的情况排查

问题:方法上添加了 @Transactional 注解,为什么没有进行回滚?


排查一:是否使用了 try catch 进行了异常捕获,并且捕获之后,没有通过 throw new RuntimeException(); 进行异常抛出。因为对于 spring aop 异常捕获原理,被拦截的方法需要显示的抛出异常,并不能进行任何处理,这样 aop 代理才能捕获到方法的异常,才能进行事务的回滚操作;默认清空下,aop 只捕获 RuntimeException 的异常,但是可以通过配置来捕获特定的异常并回滚。


排查二:是否使用了 try catch 进行了异常信息捕获,如果是可以在 catch 语句中添加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(),手动回滚事务

排查三:排查是不是产生了自调用的问题。在 spring 的 aop 代理下,只有目标方法被外部调用,目标方法才由 spring 生成的代理对象来管理;若统一类中的其他没有用 @Transactional 注解进行修饰的方法内部调用了 用 @Transactional 注解进行修饰的方法,有 @Transactional 注解的方法的事务将会被忽略,不发生回滚。(周氏概括:即没有使用@Transactional 注解修饰的方法调用了用 @Transactional 注解进行修饰的方法,将会导致事务失效)

备注:如果确实需要这样操作,只需要把 @Transactional 注解加在当前的类名上就可以了 或者使用 AspectJ 取代 spring aop 进行代理。


排查四:@Transactional 注解只被应用到 public 修饰的方法上;如果在 protected、private等修饰的方法上,@Transactional 注解不会报错,但是这个注解的将不会生效。


排查五:@Transactional 注解不会对当前修饰的方法的处理异常的子方法生效。比如:我们在方法 A 中声明了 @Transactional 注解,但是 A 方法的内部调用的 方法 B 和 方法 C,其中方法 B 进行了 数据库的操作,但是该部分的异常被方法 B 进行了处理并且没有进行 抛出,这样的话事务是不会生效的。如果想要事务生效,需要将子方法的事务控制交给调用的方法,在子方法中使用 @Transactional注解并通过 rollbackFor 指定定回滚的异常 或者直接将异常抛出。(周氏概括:使用@Transactional 注解修饰的A方法 调用了 没有用@Transactional 注解修饰的B方法,但是B方法使用try catch处理了异常,这将导致事务失效。使用@Transactional 注解修饰的A方法 调用了 没有用@Transactional 注解修饰的B方法,但是B方法将异常向上抛出或使用@Transactional注解并通过 rollbackFor 指定定回滚的异常,事务不会失效。)

备注:在使用事务的时候,最好把子方法的异常进行抛出,交给调用的方法进行处理。

四、SpringBoot事务传播机制(了解)

4.1 事务传播机制的定义

Spring 事务传播机制定义了多个包含了事务的方法在相互调用时,事务是如何在这些方法之间进行传递的。

4.2 事务传播机制的作用

  • 事务隔离级别是保证多个并发事务执行的可控性,而事务传播机制是保证一个事务在多个调用方法之间的可控性。
  • 事务隔离级别是解决多个事务同时调用数据库的问题,而事务传播机制是解决一个事务在多个节点中传递的问题。

4.3 Spring 事务传播机制有7种

  1. Propagation.REQUIRED: 默认的事务传播机制,它表示如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
  2. Propagation.SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
  3. Propagation.MANDATORY: 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
  4. Propagation.REQUIRES_NEW: 表示创建一个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部方法是否开启事务,该传播机制修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。
  5. Propagation.NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。
  6. Propagation.NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常。
  7. Propagation.NESTED: 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 Propagation.REQUIRED。

嵌套事务和加入事务的区别:

  • 嵌套事务:回事有问题的事务,但主事务不受影响。
  • 加入事务:如果任意一个方法出现异常,那么整个事务会回滚。

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

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

相关文章

绝对干货-讲讲设计模式之创建型设计模式的本质

创建型模式(Creational Patterns):创建型模式关注对象的创建机制,包括了如何实例化一个对象或者一组对象的方法。Java中的创建型模式有:单例模式(Singleton Pattern)、工厂模式(简单…

隐写-MISC-bugku-解题步骤

——CTF解题专栏—— 题目信息: 题目:隐写 作者:CyberFl0wer 提示:无 解题附件: 解题思路: 这张图片一看!哦呦~背景还是透明的,那我肯定要尝试给他换换色(不可以色色.jpg…

重生之我是一名程序员 42——字符分类函数

哈喽啊大家晚上好!今天呢给大家带来一些超简单的知识,大家是需要浅浅理解就行了。所以今天给大家带来的知识是——字符分类函数。 首先呢还是给大家介绍一下它们,字符分类函数是一种函数,它根据一定的规则将字符分组或分类。在编…

Map和Set小总结【温习】

目录 一、概念与模型 二、Map的使用 三、Set的说明 一些小练习 四、哈希表 1.概念 2.冲突 2.1、概念 2.2、冲突-->避免 2.3、冲突-->解决 (1)闭散列 (2)开散列 2.4、其他问题 一、概念与模型 1.概念&#xff1a…

三菱GX WORRKS3 下载与安装

目录 下载 安装 准备好安装包 对电脑系统要求 安装 因为小编公司需要,所以开始了三菱plc软件的学习,并从今天开始记录学习,希望小编的内容能帮到你,对你的学习有帮助! 下载 三菱电机官网 当然了,需要…

编程语言发展史:Java语言的出现和发展

预计更新 第一部分:早期编程语言 1.1布尔代数和机器语言 1.2汇编语言的出现和发展 1.3高级语言的兴起 第二部分:主流编程语言 1.1 C语言的诞生及其影响 1.2 C语言的发展和应用 1.3 Java语言的出现和发展 1.4 Python语言的兴起和特点 1.5 JavaScript语言…

C++函数题

短信计费 #include<bits/stdc.h> using namespace std; int n; int f(int); int main() {cin>>n;int sum0;for(int i0;i<n;i){int t;cin>>t;sumsumf(t);}cout<<sum;return 0; } int f(int a){int cnt1;cntcntn/70;return cnt*0.1; } 完数判断 #i…

【C++】类和对象(下篇)

这里是目录 构造函数&#xff08;续&#xff09;构造函数体赋值初始化列表 explicit关键字隐式类型转换 static成员友元友元函数友元类 内部类匿名对象匿名对象的作用const引用匿名对象 构造函数&#xff08;续&#xff09; 构造函数体赋值 在创建对象时&#xff0c;编译器通…

五种多目标优化算法(MOGWO、MOLPB、MOJS、NSGA3、MOPSO)求解微电网多目标优化调度(MATLAB代码)

一、多目标优化算法简介 &#xff08;1&#xff09;多目标灰狼优化算法MOGWO 多目标应用&#xff1a;基于多目标灰狼优化算法MOGWO求解微电网多目标优化调度&#xff08;MATLAB代码&#xff09;-CSDN博客 &#xff08;2&#xff09;多目标学习者行为优化算法MOLPB 多目标学习…

C/C++: 统计整数

【问题描述】 输入若干个整数&#xff0c;统计出现次数最多的那个整数。如果出现最多的整数有两个以上&#xff0c;打印最早输入的那个整数。 【输入形式】 从标准输入读取输入。第一行只有一个数字N&#xff08;1≤N≤10000&#xff09;&#xff0c;代表整数的个数。以后的N行…

佳易王幼儿园缴费系统软件编程应用实例

佳易王幼儿园缴费系统软件编程实例 佳易王幼儿园缴费系统功能&#xff1a; 1、系统设置 2、班级设置 3、其他费用名称 4、学生信息管理 5、学生缴费 6、统计报表 7、备份全部数据 软件试用版下载可以点击下方官网卡片

48. 旋转图像 --力扣 --JAVA

题目 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 解题思路 顺时针旋转90度 上下翻转 对角线翻转&#xff1b;两次两层循环…

由走“贸工技”的联想联想到传统OEM,带给了自己那些思考?

2022年1月16日&#xff0c;自己来到魔都的第1597天&#xff0c;这城市还是保持着相似的容颜&#xff0c;而自己却悄悄的起了变化。 以前对时间概念其实不是特别敏感&#xff0c;感觉自己有大把的时光可以浪费&#xff08;虽然知道死亡是个永远无法逃避的话题&#xff09;&#…

【华为OD】【统一考试C卷真题】100%通过:剩余银饰的重量 python 源码实现

【华为OD】【统一考试C卷真题】100%通过&#xff1a;剩余银饰的重量 python 源码实现 目录 题目描述&#xff1a; 示例1 示例2 代码实现&#xff1a; 题目描述&#xff1a; 有N块二手市场收集的银饰&#xff0c;每块银饰的重量都是正整数&#xff0c;收集到的银饰会被熔…

MATLAB 和 Simulink 官方文档下载地址

MATLAB 官方文档中文版下载网址&#xff1a; https://ww2.mathworks.cn/help/pdf_doc/matlab/index.html 如图&#xff1a; MATLAB 官方文档英文版下载网址&#xff1a; https://ww2.mathworks.cn/help/pdf_doc/matlab/index.html?langen 如图&#xff1a; Simulink 官…

Vue - Vue配置proxy代理,开发、测试、生产环境

1、新建三个环境的配置文件 在src同级目录也就是根目录下新建文件&#xff1a;.env.development&#xff08;开发环境&#xff09;、.env.test&#xff08;测试环境&#xff09;、.env.production文件&#xff08;生产环境&#xff09; 2、三个环境的配置文件 开发环境 .env…

重量级消息,微软将ThreadX RTOS全家桶贡献给Eclipse基金会,免费供大家商用,宽松的MIT授权方式

从明年第1季度开始&#xff0c;任何人&#xff0c;任何厂家的芯片都可以免费商用&#xff0c;MIT授权就这点好。 贡献出来后&#xff0c;多方可以一起努力开发&#xff0c;当前首批兴趣小组AMD, Cypherbridge, Microsoft, NXP, PX5, Renesas, ST Microelectronics, Silicon Lab…

MYSQL基础知识之【索引】

文章目录 前言MySQL 索引普通索引创建索引修改表结构(添加索引)创建表的时候直接指定删除索引的语法唯一索引创建索引修改表结构创建表的时候直接指定使用ALTER 命令添加和删除索引使用 ALTER 命令添加和删除主键显示索引信息 后言 前言 hello world欢迎来到前端的新世界 &…

cephadm部署ceph quincy版本,使用ceph-csi连接

环境说明 IP主机名角色 存储设备 192.168.2.100 master100 mon,mgr,osd,mds,rgw 大于5G的空设备192.168.2.101node101mon,mgr,osd,mds,rgw大于5G的空设备192.168.2.102node102mon,mgr,osd,mds,rgw大于5G的空设备 关闭防火墙 关闭并且禁用selinux 配置主机名/etc/hosts …

HarmonyOS(五)—— 认识页面和自定义组件生命周期

前言 在前面我们通过如何创建自定义组件一文知道了如何如何自定义组件以及自定义组件的相关注意事项&#xff0c;接下来我们认识一下页面和自定义组件生命周期。 自定义组件和页面的关系 在开始之前&#xff0c;我们先明确自定义组件和页面的关系 自定义组件&#xff1a;Co…