Spring事务及其传播机制(一)

news2025/2/24 13:03:38

目录

1.事务回顾

1.1什么是事务

1.2事务的四大重要特性(ACID)

1.3事务的操作

2.Spring中事务的实现

2.1编程式事务(了解)

2.2声明式事务@Transactional

3.@Transactional作用

3.1重新抛出异常 

3.2手动回滚事务


1.事务回顾

在数据库阶段我们已经学习过事务了

1.1什么是事务

事务是一组操作的集合,是一个不可分割的操作.
事务会把所有的操作作为一个整体,一起向数据库提交或者是撤销操作请求.所以这组操作要么同时成功,要么同时失败.

1.2事务的四大重要特性(ACID)

事务具有以下四个重要特性,通常称为 ACID 特性:

  1. 原子性(Atomicity):事务中的所有操作要么全部成功,要么全部失败回滚。如果事务中的某个操作失败,整个事务会撤销,就好像整个事务从未执行过一样。

  2. 一致性(Consistency):事务执行的结果必须使数据库从一个一致性状态转变到另一个一致性状态。这意味着数据库中的数据必须始终满足预定的规则和约束。

  3. 隔离性(Isolation):多个事务并发执行时,它们之间相互隔离,一个事务的执行不能被其他事务干扰。每个事务都感觉自己在独立地操作数据库。

  4. 持久性(Durability):一旦事务成功提交,其对数据库的更改就会永久保存,即使系统出现故障也不会丢失。

1.3事务的操作

事务的操作主要有三步:
1.开启事务:start transaction/begin(一组操作前开启事务)
2.提交事务:commit(这组操作全部成功,提交事务)
3.回滚事务:rollback (这组操作中间任何一个操作出现异常,回滚事务)

 -- 开启事务
 start transaction; 

 -- 提交事务 
 commit;

 -- 回滚事务
 rollback;

2.Spring中事务的实现

前面课程我们讲了MySQL的事务操作,Spring对事务也进行了实现.
Spring中的事务操作分为两类:编程式事务、声明式事务

2.1编程式事务(了解)

编程式事务为手动写代码操作事务,Spring手动操作事务和上面MySQL操作事务类似,有3个重要操作步骤:

  1. 开启事务(获取事务)
  2. 提交事务
  3. 回滚事务

 SpringBoot内置了两个对象:
1.DataSourceTransactionManager事务管理器.用来获取事务(开启事务),提交或回滚事务
2.TransactionDefinition是事务的属性,在获取事务的时候需要将TransactionDefinition传递进去从而获得一个事务TransactionStatus
我们还是根据代码的实现来学习:

 @RequestMapping("/user") 
 @RestController
 public class UserController { 
     // JDBC 事务管理器
     @Autowired
     private DataSourceTransactionManager dataSourceTransactionManager;
     // 定义事务属性 
     @Autowired
     private TransactionDefinition transactionDefinition;

     @Autowired
     private UserService userService;

     @RequestMapping("/registry")
     public String registry(String name,String password){
        // 开启事务
         TransactionStatus transactionStatus = dataSourceTransactionManager
                .getTransaction(transactionDefinition);
        //⽤户注册
        userService.registryUser(name,password); 
        //提交事务
         dataSourceTransactionManager.commit(transactionStatus); 
        //回滚事务
         //dataSourceTransactionManager.rollback(transactionStatus);
         return "注册成功 ";
     }
 }

观察事务提交:

 //提交事务
 dataSourceTransactionManager.commit(transactionStatus);

运行程序: http://127.0.0.1:8080/user/registry?name=admin&password=admin

观察数据库的结果, 数据插入成功.

观察事务回滚:

 //回滚事务
 dataSourceTransactionManager.rollback(transactionStatus);

运行程序:

观察数据库, 虽然程序返回"注册成功", 但数据库并没有新增数据.

以上代码虽然可以实现事务, 但操作也很繁琐, 有更简单的实现方法:声明式事务

2.2声明式事务@Transactional

声明式事务的实现很简单,只需要在需要事务的方法上添加@Transactional注解就可以实现了。无需手动开启事务和提交事务,进入方法时自动开启事务,方法执行完会自动提交事务,如果中途发生了没有处理的异常会自动回滚事务.
我们来看代码实现:

 @RequestMapping("/trans") 
 @RestController
 public class TransactionalController { 
     @Autowired
     private UserService userService; 

     @Transactional
     @RequestMapping("/registry")
     public String registry(String name,String password){
        //⽤⼾注册
        userService.registryUser(name,password);
         return "注册成功 ";
     }
 }

运行程序,发现数据插入成功.

修改程序, 使之出现异常

 @Slf4j
 @RequestMapping("/trans")
 @RestController
 public class TransactionalController { 
     @Autowired
     private UserService userService; 

     @Transactional
     @RequestMapping("/registry")
     public String registry(String name,String password){
        //⽤⼾注册
        userService.registryUser(name,password);
         log.info("⽤户数据插⼊成功"); 
        //强制程序抛出异常
        int a = 10/0;
         return "注册成功 ";
     }
 }

运行程序:

发现虽然日志显示数据插入成功, 但数据库却没有新增数据, 事务进行了回滚.

我们一般会在业务逻辑层当中来控制事务,因为在业务逻辑层当中,一个业务功能可能会包含多个数据访问的操作,在业务逻辑层来控制事务,我们就可以将多个数据访问操作控制在一个事务范围内.上述代码在Controller中书写,只是为了方便学习.

3.@Transactional作用

@Transactional可以用来修饰方法或类:
修饰方法时:只有修饰public方法时才生效(修饰其他方法时不会报错,也不生效)[推荐]
修饰类时:对@Transactional修饰的类中所有的public方法都生效.
方法/类被@Transactional注解修饰时,在目标方法执行开始之前,会自动开启事务,方法执行结束之后,自动提交事务.
如果在方法执行过程中,出现异常,且异常未被捕获,就进行事务回滚操作。如果异常被程序捕获,方法就被认为是成功执行,依然会提交事务。

修改上述代码,对异常进行捕获

 @Transactional
 @RequestMapping("/registry")
 public String registry(String name,String password){ 
     //⽤户注册
     userService.registryUser(name,password);
     log.info("⽤户数据插⼊成功"); 
     //对异常进⾏捕获
     try {
        //强制程序抛出异常
        int a = 10/0;
     }catch (Exception e){
        e.printStackTrace(); 
     }
     return "注册成功 "; 
 }

运行程序, 发现虽然程序出错了, 但是由于异常被捕获, 所以事务依然得到了提交. 如果需要事务进行回滚, 有以下两种方式:

3.1重新抛出异常 

 @Transactional
 @RequestMapping("/registry")
 public String registry(String name,String password){ 
     //⽤户注册
     userService.registryUser(name,password);
     log.info("⽤户数据插⼊成功"); 
     //对异常进⾏捕获
     try {
        //强制程序抛出异常
        int a = 10/0;
     }catch (Exception e){
        //将异常重新抛出去
        throw e; 
     }
     return "注册成功 "; 
 }

重新抛出异常后事务会进行回滚

3.2手动回滚事务

使用TransactionAspectSupport.currentTransactionStatus()得到当前的事务,并设置setRollbackOnly

 @Transactional
 @RequestMapping("/registry")
 public String registry(String name,String password){ 
     //⽤⼾注册
     userService.registryUser(name,password);
     log.info("⽤户数据插⼊成功"); 
     //对异常进⾏捕获
     try {
        //强制程序抛出异常
        int a = 10/0;
     }catch (Exception e){
        // ⼿动回滚事务
         TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 
     }
     return "注册成功 "; 
 }

代码解释: 

TransactionAspectSupport是 Spring 框架中与事务处理相关的一个支持类。 currentTransactionStatus()方法用于获取当前正在执行的事务的状态对象。 setRollbackOnly()方法用于将获取到的当前事务状态设置为只回滚。这意味着无论事务中后续的操作结果如何,整个事务都会被回滚,不会进行提交。

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

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

相关文章

【Redis】SpringBoot连接Redis

1. 创建项目并配置文件 勾选NoSQL中的 Spring Data Redis。当然,把 Web 中的 SpringWeb 也勾选一下.方便写接口进行后续测试。 在 application.yml 中配置 2. 不同数据类型使用Demo 在SpringBoot中,为我们提供了StringRedisTemplate类,供我们处理一些文…

详细介绍MySQL的索引(上)

索引 索引概述 索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结…

VisualStudio2019受支持的.NET Core

1.VS Studio2019受支持的.NET Core? 适用于 Visual Studio 的 .NET SDK 下载 (microsoft.com) Visual Studio 2019 默认并不直接支持 .NET 6 及以上版本。要使用 .NET 6 或更高版本,你需要在 Visual Studio 2019 中采取额外步骤,比如安装相应…

<电力行业> - 《第9课:输电(二)》

4 输送电能流程 输送电能总共有:发电站→升压变压器→高压输电线→降压变压器→用电单位等五个流程。 电力工业初期,发电厂建在电力用户附近,直接向用户送电,所以那个时候只有发电和用电两个环节。 随着电力生产规模和负荷中心规…

QTreeView第一列自适应

通过setStretchLastSection(bool stretch)可以设置最后一列自适应,对于QTreeView,stretch默认为true。但有时候我们需要设置第一列自适应,比如文件浏览器,共有名称、大小和修改日期三列,大小和日期的宽度几乎是固定的,但名称却可长可短,此时我们希望在窗口大小变化时,第…

一元线性回归-R语言

# # 安装包 # install.packages(ggplot2) # library(ggplot2) Sys.setlocale(category LC_ALL, locale English_United States.1252) # Sys.setlocale("LC_ALL","Chinese") x <- c(18, 20, 22, 24, 26, 28, 30) y <- c(26.86, 28.35, 28.87,28.75,…

【源码+文档+调试讲解】actual self 服装店的设计与实现

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统服装销售信息管理难度大&#xff0c;容错率低&#xff0c…

封装了一个iOS滚动厨窗效果

效果图 背景 我们要实现如图的厨窗效果&#xff0c;不能通过在tableView底部添加一个背景图片的方式&#xff0c;因为这需要修改整个tableView的背景色为透明&#xff0c;影响到的范围太大&#xff0c;只能将这个效果局限在这个cell 中&#xff0c;然后通过监听tableView的滚动…

Python应用开发——30天学习Streamlit Python包进行APP的构建(12)

st.checkbox 显示复选框部件。 Function signature[source] st.checkbox(label, valueFalse, keyNone, helpNone, on_changeNone, argsNone, kwargsNone, *, disabledFalse, label_visibility"visible") Returns (bool) Whether or not the checkbox is checked. …

认识100种电路之放大电路

在电子技术的广袤世界中&#xff0c;放大电路犹如一颗璀璨的明珠&#xff0c;发挥着至关重要的作用。那么&#xff0c;为什么电路需要放大&#xff1f;放大的原理又是什么&#xff1f;实现放大又需要用到哪些元器件以及数量如何呢&#xff1f;接着往下看&#xff0c;会解开你的…

leetCode.93. 复原 IP 地址

leetCode.93. 复原 IP 地址 题目思路&#xff1a; 代码 // 前导零的判断方法&#xff1a;如果第一个数是0&#xff0c;且第二个数还有数据&#xff0c;那就是前导0&#xff0c;要排除的 // 注意跟单个 0 区分开 class Solution { public:vector<string> res;vector<…

redis实战-缓存雪崩问题及解决方案

定义理解 缓存雪崩是指在同一时间段&#xff0c;大量缓存的key同时失效&#xff0c;或者Redis服务宕机&#xff0c;导致大量请求到达数据库&#xff0c;带来巨大压力 和缓存击穿的区别&#xff1a; 缓存雪崩是由于缓存中的大量数据同时失效或缓存服务器故障引起的&#xff1b…

ESP32-C3模组上跑通MQTT(6)—— tcp例程(1)

接前一篇文章:ESP32-C3模组上跑通MQTT(5) 《ESP32-C3 物联网工程开发实战》 一分钟了解MQTT协议 ESP32 MQTT API指南-CSDN博客 ESP-IDF MQTT 示例入门_mqtt outbox-CSDN博客 ESP32用自签CA进行MQTT的TLS双向认证通信_esp32 mqtt ssl-CSDN博客 特此致谢! 本回开始正式讲…

python进阶函数

目录 函数多返回值函数多种传参方式匿名函数 函数多返回值 问&#xff1a;如果一个函数如些两个return&#xff08;如下所示&#xff09;&#xff0c;程序如何执行&#xff1f; def return_num():return 1return 2result return_num() print(result)答&#xff1a;只执行了第…

玩游戏就能学习亚马逊云科技AWS技术并通过热门技术认证考试??

亚马逊AWS限时活动&#xff0c;玩免费游戏Cloud Quest Practitioner送AWS云从业证书考试25%折扣券(价值171元)&#xff0c;玩游戏的同时还能学知识一举两得。Cloud Quest是AWS出的一款3D角色扮演游戏/虚拟城市建造形式的实验课程(游戏画面有点像天际线)&#xff0c;大家通过完成…

uniapp启动页面鉴权页面闪烁问题

在使用uni-app开发app 打包完成后如果没有token&#xff0c;那么就在onLaunch生命周期里面判断用户是否登录并跳转至登录页。 但是在app中页面会先进入首页然后再跳转至登录页&#xff0c;十分影响体验。 处理方法&#xff1a; 使用plus.navigator.closeSplashscreen() 官网…

《HelloGitHub》第 99 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对编程感兴趣&#xff01; 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 Python、…

网络基础:路由路由协议

路由是指在计算机网络中选择路径来传输数据包的过程和机制&#xff1b;它包括路径选择、数据包转发、以及维持网络连接所需的各种协议和算法&#xff0c;路由的目标是确保数据包能够高效且可靠地从源设备传输到目标设备&#xff1b;常见的能够实现路由功能网络设备有&#xff1…

期末重现题型--错题集

看书里的定义&#xff1a;链表是一种常见而重要的动态存储分布的数据结构。它由若干个同一结构类型的“结点”依次串联而成的。

【理解】关于正点原子i.MX6ULL LCD计算式的理解

文章目录 1 描述2 疑问3 理解 1 描述 在《【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.81.pdf》&#xff0c;P560页&#xff0c;第二十四章 RGBLCD显示实验中提到&#xff0c;LCD屏幕显示一行所需要的时间&#xff1a; t H S P W H B P H O Z V A L H F P ① t HSPW …