【Spring Boot】Spring 事务探秘:核心机制与应用场景解析

ops/2025/2/11 18:13:12/

前言

???本期讲解关于spring 事务介绍~~~

??感兴趣的小伙伴看一看小编主页:-CSDN博客

?? 你的点赞就是小编不断更新的最大动力

??那么废话不多说直接开整吧~~

目录

???1.事务

??1.1什么是事务

??1.2为什么需要事务

??1.3操作事务

???2.Spring事务

??2.1编程式事务

??2.2声明式事务

1.异常捕获

2.异常捕获再次抛出

3.编译时异常

4.运行时异常

5@transaction属性

6.@transaction总结

???3.总结

**??**1.事务

??1.1什么是事务

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

??1.2为什么需要事务

假如有以下场景,若在存钱的过程中,A账户减少了100元,本应该就是在B账户中多出100元,但是

如果没有事务,第步执成功了, 第步执失败了, 那么A 账的100 元就平故消失了. 如果使事务就可以解决这个问题, 让这组操作要么起成功, 要么起失败

就可以解决上述的问题了;

??1.3操作事务

数据库中操作事务有以下几个步骤:

1. 开启事start transaction/ begin (组操作前开启事务)

2. 提交事务: commit (这组操作全部成功, 提交事务)

3. 回滚事务: rollback (这组操作中间任何个操作出现异常, 回滚事务)

当然这是在MySQL阶段学习的几个事务操作步骤,但是spring也是有事务的操作的,那么我们接着往下面看看~~~

**??**2.Spring事务

MySQL对于事务进行了实现,Spring对事务也是进行了实现,具体有两种实现方式:

Spring 中的事务操作分为两类:

1. 编程式事务(动写代码操作事务)
2. 声明式事务(利注解动开启和提交事务)

首先,要进行之前mybatis的数据库操作,这里小编就不在进行演示了;

??2.1编程式事务

SpringBoot 内置了两个对象:
1. DataSourceTransactionManager 事务管理器. 来获取事务(开启事务), 提交或回滚事务
2. 的TransactionDefinition 是事务的属性, 在获取事务的时候需要将
TransactionDefinition 传递进去从获得个事务 TransactionStatus

具体的代码如下所示:

@RestController
@RequestMapping("/user")
public class UserController {//手动改开启事务@Autowiredprivate DataSourceTransactionManager dataSourceTransactionManager;@Autowiredprivate TransactionDefinition transactionDefinition;@Autowiredprivate UserService userService;@RequestMapping("/regist")public boolean regist(String userName,String password){//开启事务TransactionStatus transactionStatus=dataSourceTransactionManager.getTransaction(transactionDefinition);//操作数据库userService.registUser(userName,password);//提交事务dataSourceTransactionManager.commit(transactionStatus);//回滚事务dataSourceTransactionManager.rollback(transactionStatus);return true;}
}

解释:

注意这里要注入事务管理器对象,以及事务属性对象,这两个相当于是获取事务的状态,然后通过事务管理器通过提交或者回滚来操作我们的事务状态;

操作完数据库后,才进行事务的对应的处理哦~~~

具体的日志打印如下:

此时就是进行了事务的回滚,如果进行了事务的提交,那么就会存在一个commit单词的日志;

这里就是进行了事务的提交;

当然这里小编演示的时候,需要注释掉其中一个事务的操作,因为不可能事务提交又进行了回滚是吧~~~

??2.2声明式事务

这里的操作分为两步,主要式通过注解进行事务的自动开启:

第一步:添加依赖

<dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId>
</dependency>

但是这里的依赖添加,这里小编添加了lombok,spring web,mybatis farmwork,mysql driver,并没有引入这里的依赖;

第二步:添加注解

在需要事务的法上添加 @Transactional 注解就可以实现了. 需动开启事务和提交事
务, 进法时动开启事务, 法执完会动提交事务, 如果中途发了没有处理的异常会动
回滚事务

代码如下所示:

@RestController
@RequestMapping("/trans")
public class TransController {@Autowiredprivate UserService userService;@Transactional @RequestMapping("t1")public Boolean register(String userName, String password){Integer result = userService.registUser(userName, password);System.out.println("插入用户表, result: "+ result);return true;}

当然,如果这里的存在异常情况下时,代码如下所示:

@Transactional@RequestMapping("t1")public Boolean register(String userName, String password){Integer result = userService.registUser(userName, password);System.out.println("插入用户表, result: "+ result);int a = 10/0;return true;}

那么此时就会发生回滚,数据库就不会插入对应的数据;

但是对于所有发生了异常,此时事务都会进行回滚吗?当然不是,还要分为以下情况

1.异常捕获

当我们进行异常捕获后,代码如下所示

@RestController
@RequestMapping("/trans")
public class TransController {@Autowiredprivate UserService userService;/**程序异常,捕获并处理,这里结果就是提交*/@Transactional@RequestMapping("t1")public Boolean register(String userName, String password){Integer result = userService.registUser(userName, password);System.out.println("插入用户表, result: "+ result);try {int a = 10/0;}catch (Exception e){//打印堆栈信息e.printStackTrace();}return true;}

解释:

这里就是通过try catch后进行堆栈信息的打印,所以最后就会进行事务的提交

(事务的提交与否,主要查看日志,是否存在commit的单词,或者去观察在数据库中数据是否进行了插入的操作)

2.异常捕获再次抛出

代码如下所示:

 /**捕获异常之后,没有处理,直接再次抛出,回滚*/@Transactional@RequestMapping("t2")public Boolean register1(String userName, String password){Integer result = userService.registUser(userName, password);System.out.println("插入用户表, result: "+ result);try {int a = 10/0;}catch (Exception e){throw e;}return true;}

解释:

在捕获到这里的算数异常后,再次把异常进行抛出,那么此时就相当于是没有进行捕获的,那么事务就会进行回滚,并且这里还可以进行手动回滚;

在捕获异常后,添加:

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

此时就会进行手动的回滚操作;

3.编译时异常

代码如下所示:

/***  事务提交*/@Transactional@RequestMapping("/t4")public Boolean r4(String userName, String password) throws IOException {Integer result = userService.registUser(userName, password);System.out.println("插入用户表, result: "+ result);if (true){throw new IOException();//为编译时异常}return true;}

解释:

在事务的提交中,只有运行时异常,以及rerror会触发回滚,但是在这里的编译时异常是不可以回滚的(大致的可以理解为就是编译时异常有明显的报错,希望我们自己改正,这里事务就不管了)

当然还有一种情况

/***  事务回滚*/@Transactional@SneakyThrows@RequestMapping("/t5")public Boolean r5(String userName, String password)  {Integer result = userService.registUser(userName, password);System.out.println("插入用户表, result: "+ result);if (true){throw new IOException();}//在反编译中这里会捕获异常,并再次抛出return true;}

这里的事务结果就是回滚,为什么呢?这里添加了注解@SneakyThrows,我们在反编译文件中可以看到这里还进行了异常的捕获,但是没有处理,直接把异常抛出了,所以这里就是第二种情况

4.运行时异常

代码如下所示:

/***  事务回滚*/@Transactional@RequestMapping("/t6")public Boolean r6(String userName, String password)  {Integer result = userService.registUser(userName, password);System.out.println("插入用户表, result: "+ result);if (true){//这里抛出的就是运行时异常,需要进行回滚throw new RuntimeException();}return true;}

这里的的事务那么就是直接回滚了,小编不再进行过多的赘述;

5@transaction属性

1. rollbackFor: 异常回滚属性. 指定能够触发事务回滚的异常类型. 可以指定多个异常类型

2. Isolation: 事务的隔离级别. 默认值为 Isolation.DEFAULT

3. propagation: 事务的传播机制. 默认值为 Propagation.REQUIRED

注意:

@Transactional 默认只在遇到运时异常和Error时才会回滚, 运时异常不回滚. 即
Exception的类中, 除了RuntimeException及其类其他的会不进行回滚

但是我们可以指定这里rollbackfor为所有异常类型,所以对于所有的异常,此时都会进行回滚的操作;代码如下所示:

@Transactional(rollbackFor = Exception.class, isolation = Isolation.DEFAULT)//设置所有回滚异常类型@RequestMapping("/r7")public Boolean r7(String userName, String password) throws IOException {Integer result = userService.registUser(userName, password);System.out.println("插入用户表, result: "+ result);if (true){throw new IOException();}return true;}
6.@transaction总结

@Transactional 可以来修饰法或类:
修饰法时: 只有修饰public 法时才效(修饰其他法时不会报错, 也不效)[推荐]
修饰类时: 对 @Transactional 修饰的类中所有的 public 法都效.
法/类被 @Transactional 注解修饰时, 在标法执开始之前, 会动开启事务, 法执结束
之后, 动提交事务.

如果在法执过程中, 出现异常, 且异常未被捕获, 就进事务回滚操作.
如果异常被程序捕获, 法就被认为是成功执, 依然会提交事务,但是捕获后重新抛出,就会回滚,若为运行时异常,那么也会进行回滚,但是编译时异常在不添加SneakyThrow时为提交;

**??**3.总结

本期主要讲解了关于事务,以及Spring事务的知识,对于Spring 事务的两种方式,小编都进行了代码的演示;

???~~~~最后希望与诸君共勉,共同进步!!!


???以上就是本期内容了, 感兴趣的话,就关注小编吧。

???期待你的关注~~~


http://www.ppmy.cn/ops/157574.html

相关文章

【基于SprintBoot+Mybatis+Mysql】电脑商城项目之修改密码和个人资料

&#x1f9f8;安清h&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;【Spring篇】【计算机网络】【Mybatis篇】 &#x1f6a6;作者简介&#xff1a;一个有趣爱睡觉的intp&#xff0c;期待和更多人分享自己所学知识的真诚大学生。 目录 &#x1f383;1.修改密码 -持久…

【Ubuntu】安装和使用Ollama的报错处理集合

Ollama是一个开源的大型语言模型(LLM)推理服务器,为用户提供了灵活、安全和高性能的语言模型推理解决方案。 Ollama的主要特点是它能够运行多种类型的大型语言模型,包括但不限于Alpaca、Llama、Falcon、Mistral等,而无需将模型上传至服务器。这意味着用户可以直接在本地或…

Proxy vs DefineProperty

几年前校招面试的时候被问过一个问题&#xff0c;Vue3/Vue2 如何实现数据和UI的同步&#xff0c;其区别是什么&#xff0c;Vue3的方式优势是什么&#xff1f; 当时背了八股&#xff0c;默写了一通不知所云的代码&#xff0c;面试没过&#xff0c;再也没写过Vue。 今天拿出点时…

PromptSource官方文档翻译

目录 核心概念解析 提示模板&#xff08;Prompt Template&#xff09; P3数据集 安装指南 基础安装&#xff08;仅使用提示&#xff09; 开发环境安装&#xff08;需创建提示&#xff09; API使用详解 基本用法 子数据集处理 批量操作 提示创建流程 Web界面操作 手…

【AI-26】常见的监督学习方法集合

监督学习是机器学习中的一个重要类别&#xff0c;它基于有标签的数据进行模型训练&#xff0c;目标是让模型学会从输入数据预测对应的输出标签。以下是一些常见的监督学习方法及其通俗易懂的解释&#xff1a; 线性回归 原理&#xff1a;假设输入特征和输出标签之间存在线性关…

哪些专业跟FPGA有关?

FPGA产业作为近几年新兴的技术领域&#xff0c;薪资高、待遇好&#xff0c;吸引了大量的求职者。特别是对于毕业生&#xff0c;FPGA领域的岗位需求供不应求。那么&#xff0c;哪些专业和FPGA相关呢&#xff1f; 哪些专业跟FPGA有关&#xff1f; 微电子学与固体电子学、微电子科…

如何在WPS和Word/Excel中直接使用DeepSeek功能

以下是将DeepSeek功能集成到WPS中的详细步骤&#xff0c;无需本地部署模型&#xff0c;直接通过官网连接使用&#xff1a;1. 下载并安装OfficeAI插件 &#xff08;1&#xff09;访问OfficeAI插件下载地址&#xff1a;OfficeAI助手 - 免费办公智能AI助手, AI写作&#xff0c;下载…

【AI】在Ubuntu中使用docker对DeepSeek的部署与使用

这篇文章前言是我基于部署好的deepseek-r1:8b模型跑出来的 关于部署DeepSeek的前言与介绍 在当今快速发展的技术环境中&#xff0c;有效地利用机器学习工具来解决问题变得越来越重要。今天&#xff0c;我将引入一个名为DeepSeek 的工具&#xff0c;它作为一种强大的搜索引擎&a…