Spring事务和事务传播机制(1)
前言🍭
❤️❤️❤️SSM专栏更新中,各位大佬觉得写得不错,支持一下,感谢了!❤️❤️❤️
Spring + Spring MVC + MyBatis_冷兮雪的博客-CSDN博客
在Spring框架中,事务管理是一种用于维护数据库操作的一致性和完整性的机制。Spring事务管理提供了灵活的方式来处理事务,包括事务的创建、提交、回滚以及事务的传播行为。
一、为什么需要事务?🍭
事务定义:
将一组操作封装成一个执行单元(封装到⼀起),要么全部成功,要么全部失败。
为什么要用事务?
比如转账分为两个操作:
第一步操作:A 账户 -100 元。
第二步操作:B 账户 +100 元。
如果没有事务,第一步执行成功了,第二步执行失败了,那么 A 账户平白无故的 100 元就“人间蒸 发”了。而如果使用事务就可以解决这个问题,让这⼀组操作要么⼀起成功,要么⼀起失败。
二、Spring 中事务的实现🍭
Spring 中的事务操作分为两类:
- 编程式事务(手动写代码操作事务)。
- 声明式事务(利用注解自动开启和提交事务)。
在开始讲解它们之前,咱们先来回顾事务在 MySQL 中是如何使用的。
1、MySQL 中的事务使用🍉
事务在 MySQL 有 3 个重要的操作:开启事务、提交事务、回滚事务,它们对应的操作命令如下:
-- 开启事务
start transaction;
-- 业务执行
-- 提交事务
commit;
回滚事务
rollback;
2、Spring 编程式事务(了解)🍉
Spring 手动操作事务和上面MySQL 操作事务类似,它也是有 3 个重要操作步骤:
- 开启事务(获取事务)。
- 提交事务。
- 回滚事务。
SpringBoot 内置了两个对象,DataSourceTransactionManager 用来获取事务(开启事务)、提交或回滚事务的,而TransactionDefinition 是事务的属性,在获取事务的时候需要将 TransactionDefinition 传递进去从而获得⼀个事务 TransactionStatus,实现代码如下:
package com.example.demo.controller;import com.example.demo.entity.UserInfo;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.time.LocalDateTime;@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@Autowiredprivate DataSourceTransactionManager transactionManager;@Autowiredprivate TransactionDefinition transactionDefinition;@RequestMapping("/add")public int add(UserInfo userInfo){// 非空效验if (userInfo == null || !StringUtils.hasLength(userInfo.getUsername())|| !StringUtils.hasLength(userInfo.getPassword())) {return 0;}// 1.开始事务TransactionStatus transactionStatus =transactionManager.getTransaction(transactionDefinition);// 手动设置创建时间和修改时间的默认值userInfo.setCreatetime(LocalDateTime.now().toString());userInfo.setUpdatetime(LocalDateTime.now().toString());int result = userService.add(userInfo);System.out.println("添加:" + result);// 2.回滚事务transactionManager.rollback(transactionStatus);return result;}
}

因为回滚了事务,所以数据库中不会有wangwu这个用户。
从上述代码可以看出,以上代码虽然可以实现事务,但操作也很繁琐,有没有更简单的实现方法呢?请看下面声明式事务。
3、Spring 声明式事务(自动)🍉
声明式事务的实现很简单,只需要在需要的方法上添加 @Transactional 注解就可以实现了,无需手动开启事务和提交事务,进入方法时自动开启事务,方法执行完会自动提交事务,如果中途发生了没有处理的异常会自动回滚事务,具体实现代码如下:
@Transactional// 声明式事务(自动提交)@RequestMapping("/insert")public Integer insert(UserInfo userInfo) {// 非空效验if (userInfo == null || !StringUtils.hasLength(userInfo.getUsername()) ||!StringUtils.hasLength(userInfo.getPassword())) {return 0;}// 添加用户int result = userService.add(userInfo);return result;} 接下里使用以下代码,分别设置 @Transactional 注解和不设置 @Transactional,观察它们的执行区别:

如果添加了 @Transactional注解就不会添加用户,因为程序报错了,它会自动回滚。如果没有@Transactional注解,就会添加用户,然后给前端报错,这是非常危险的。

Ⅰ、@Transactional 作用范围 🍓
@Transactional 可以用来修饰方法或类:
- 修饰方法时:需要注意只能应用到 public 方法上,否则不生效。推荐此种用法。
- 修饰类时:表明该注解对该类中所有的 public 方法都生效。
Ⅱ、@Transactional参数说明🍓
| 参数 | 作用 |
| value | 当配置了多个事务管理器时,可以使用该属性指定选择哪个事务管理器. |
| transactionManager | 当配置了多个事务管理器时,可以使用该属性指定选择哪个事务管理器. |
| propagation | 事务的传播行为,默认值为Propagation.REQUIRED |
| isolation | 事务的隔离级别.默认值为Isolation.DEFAULT |
| timeout | 事务的超时时间,默认值为-1.如果超过该时间限制但事务还没有完成,则自动回滚事务. |
| readOnly | 指定事务是否为只读事务,默认值为false;为了忽略那些不需要事务的方法,比如读取数据, 可以设置read-only为true. |
| rollbackFor | 用于指定能够触发事务回滚的异常类型,可以指定多个异常类型. |
| rollbackForClassName | 用于指定能够触发事务回滚的异常类型,可以指定多个异常类型. |
| noRollbackFor | 抛出指定的异常类型,不回滚事务.也可以指定多个异常类型. |
| noRollbackForClassName | 抛出指定的异常类型,不回滚事务,也可以指定多个异常类型. |
Ⅲ、注意事项🍓
@Transactional 在异常被捕获的情况下,不会进行事务自动回滚,验证以下代码是否会发生事务回滚:
@Transactional// 声明式事务(自动提交)@RequestMapping("/insert")public Integer insert(UserInfo userInfo) {// 非空效验if (userInfo == null || !StringUtils.hasLength(userInfo.getUsername()) ||!StringUtils.hasLength(userInfo.getPassword())) {return 0;}// 添加用户int result = userService.add(userInfo);try {int num=10/0;} catch (Exception e) {System.out.println(e.getMessage());}return result;} 
数据库中也有了wangwu:
![]()
事务并没有进行回滚。
事务不会自动回滚解决方案🍓
①解决方案1🍒
对于捕获的异常,事务是会自动回滚的,因此解决方案1就是可以将异常重新抛出,具体实现如下:
@Transactional// 声明式事务(自动提交)@RequestMapping("/insert")public Integer insert(UserInfo userInfo) {// 非空效验if (userInfo == null || !StringUtils.hasLength(userInfo.getUsername()) ||!StringUtils.hasLength(userInfo.getPassword())) {return 0;}// 添加用户int result = userService.add(userInfo);try {int num=10/0;} catch (Exception e) {System.out.println(e.getMessage());throw e;}return result;}
②解决方案2🍒
手动回滚事务,在方法中使用TransactionAspectSupport.currentTransactionStatus() 可 以得到当前的事务,然后设置回滚方法 setRollbackOnly 就可以实现回滚了,具体实现代码如下:
@Transactional// 声明式事务(自动提交)@RequestMapping("/insert")public Integer insert(UserInfo userInfo) {// 非空效验if (userInfo == null || !StringUtils.hasLength(userInfo.getUsername()) ||!StringUtils.hasLength(userInfo.getPassword())) {return 0;}// 添加用户int result = userService.add(userInfo);try {int num=10/0;} catch (Exception e) {System.out.println(e.getMessage());/*throw e;*/TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}return result;}
Ⅳ、@Transactional 工作原理🍓
@Transactional 是基于 AOP 实现的,AOP又是使用动态代理实现的。如果目标对象实现了接口,默认情况下会采用JDK 的动态代理,如果目标对象没有实现了接口,会使用CGLIB 动态代理。
@Transactional 在开始执行业务之前,通过代理先开启事务,在执行成功之后再提交事务。如果中途遇到的异常,则回滚事务。
@Transactional 实现思路预览:

@Transactional 具体执行细节如下图所

三、事务隔离级别🍭
1、事务特性🍉
事务有4 ⼤特性(ACID),原子性、持久性、⼀致性和隔离性,具体概念如下:
- 原子性:⼀个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过⼀样。
- ⼀致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
- 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
- 隔离性:数据库允许多个并发事务同时对其数据进⾏读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不⼀致。事务隔离分为不同级别,包括读未提交 (
Read uncommitted)、读提交 (read committed)、可重复读 (repeatable read) 和串行化 (Serializable)。
原⼦性(Atomicity,或称不可分割性)⼀致性(Consistency)隔离性(Isolation,⼜称独立性)持久性(Durability)。
而这 4 种特性中,只有隔离性(隔离级别)是可以设置的。
为什么要设置事务的隔离级别?
设置事务的隔离级别是用来保障多个并发事务执行更可控,更符合操作者预期的。
什么是可控呢?
比如近几年比较严重的新冠病毒,我们会把直接接触到确证病例的人员隔离到酒店,而把间接接触者(和直接接触着但未确诊的人)隔离在自己的家中,也就是针对不同的人群,采取不同的隔离级别,这种隔离方式就和事务的隔离级别类似,都是采取某种行动让某个事件变的“更可控”。而事务的隔离级别就是为了防止,其他的事务影响当前事务执行的一种策略。

相关文章:
Spring事务和事务传播机制(1)
前言🍭 ❤️❤️❤️SSM专栏更新中,各位大佬觉得写得不错,支持一下,感谢了!❤️❤️❤️ Spring Spring MVC MyBatis_冷兮雪的博客-CSDN博客 在Spring框架中,事务管理是一种用于维护数据库操作的一致性和…...
如何快速在vscode中实现不同python文件的对比查看
总体而言:两种方式。一种是直接点击vscode右上角的图标(见下图)。 另一种方式就是使用快捷键啦“**Ctrl**”,用的时候选中想要对比的python文件,然后快捷键就可以达到下图效果了: 建议大家直接使用第二种…...
网络安全---Ring3下动态链接库.so函数劫持
一、动态链接库劫持原理 1.1、原理 Unix操作系统中,程序运行时会按照一定的规则顺序去查找依赖的动态链接库,当查找到指定的so文件时,动态链接器(/lib/ld-linux.so.X)会将程序所依赖的共享对象进行装载和初始化,而为什么可以使用…...
leetcode283. 移动零
难度:简单题 题目 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请注意 ,必须在不复制数组的情况下原地对数组进行操作。 思路: 一开始想,从前往后遍历&am…...
GuLi商城-前端基础Vue-生命周期和钩子函数
下图展示了实例的生命周期。你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它 的参考价值会越来越高。 VUE 的生命周期指的是组件在创建、运行和销毁过程中所经历的一系列事件,通过这些事件可以 让开发者在不同阶段进行相应的…...
输入输出+暴力模拟入门:魔法之树、染色の树、矩阵、字母加密、玫瑰鸭
秋招实习刷题网站推荐:codefun2000.com,还有题解博客:blog.codefun2000.com/。以下内容都是来自塔子哥的~ 输入输出 2023.04.15-春招-第三题-魔法之树 //#include<bits/stdc.h> #include<vector> #include<iostream>usin…...
Kubernetes的演变:从etcd到分布式SQL的过渡
DevRel领域专家Denis Magda表示,他偶然发现了一篇解释如何用PostgreSQL无缝替换etcd的文章。该文章指出,Kine项目作为外部etcd端点,可以将Kubernetes etcd请求转换为底层关系数据库的SQL查询。 受到这种方法的启发,Magda决定进一步…...
29、简单通过git把项目远程提交到gitee
简单通过git把项目远程提交到gitee 1、在gitee上创建一个仓库 2、在要提交的项目文件夹打开git 输入 git init 初始化git 然后设置下用户名和邮箱 git config --global user.name “username” git config --global user.email “yourEmail” 因为我是要把文件简单提交到…...
元宇宙之应用(04)沉浸式游戏
在数字科技迅猛发展的今天,元宇宙的概念正逐渐从科幻走向现实,重新定义了人们与虚拟世界的交互方式。在这一概念的引领下,"沉浸式游戏" 蓬勃发展,为游戏体验带来了前所未有的深度和广度。那么,为什么沉浸式游…...
浙大数据结构第八周之08-图7 公路村村通
题目详情: 现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。 输入格式: 输入数据包括城镇数目正整数N(≤1000)和候选道路数目M(…...
SpringBoot 解决跨域问题
同源策略(CORS):浏览器在解析发送的请求时,要求浏览器的路径与发送的请求的路径必须满足三个要求,即请求的协议、域名、端口号都相同,满足同源策略,才可以访问服务器,否则࿰…...
2023 年牛客多校第十场题解
C Multiplication 题意:定义 k k k-shift 数是满足 k x y ‾ y x ‾ k\overline{xy}\overline{yx} kxyyx 的数字。给定 k k k,求最大不超过 n n n 的 k k k-shift 数。 1 ≤ n ≤ 1 0 100 1 \le n \le 10^{100} 1≤n≤10100, 2 ≤…...
韦东山老师 RTOS 入门课程(一)RTOS 介绍,熟悉裸机的汇编逻辑
韦东山老师 RTOS 入门课程 课程链接:韦东山直播公开课:RTOS实战项目之实现多任务系统 第1节:裸机程序框架和缺陷_哔哩哔哩_bilibili RTOS 介绍 裸机:固定顺序执行。 中断:可以一直专心做循环里的事情,直…...
WebRTC | SDP详解
目录 一、SDP标准规范 1. SDP结构 2. SDP内容及type类型 二、WebRTC中的SDP结构 1. 媒体信息描述 (1)SDP中媒体信息格式 i. “artpmap”属性 ii. “afmtp”属性 (2)SSRC与CNAME (3)举个例子 &…...
Springboot 实践(9)springboot集成Oauth2.0授权包,5个接口文件配置详解
前文讲解实现了spring boot集成Oauth2.0,实现了授权服务器和资源服务器的搭建,并通过浏览器和postman测试,获取到了授权码,用携带授权码的URL能够争取范文到资源。 本文详细讲解spring boot集成Oauth2.0的几个重要文件接口&#…...
最新AI系统ChatGPT程序源码/支持GPT4/自定义训练知识库/GPT联网/支持ai绘画(Midjourney)+Dall-E2绘画/支持MJ以图生图
一、前言 SparkAi系统是基于国外很火的ChatGPT进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。 那么如何搭建部署AI创作ChatGPT?小编这里写一个详细图文教程吧!…...
【高频面试题】 消息中间件
文章目录 1、RabbitMQ1.1 RabbitMQ-如何保证消息不丢失1.2 RabbitMQ消息的重复消费问题如何解决的1.3 RabbitMQ中死信交换机 ? (RabbitMQ延迟队列有了解过嘛)1.4 RabbitMQ如果有100万消息堆积在MQ , 如何解决(消息堆积怎么解决)1.5 RabbitMQ的高可用机制有了解过嘛 2、Kafka2.…...
物联网智慧安防实训综合实训基地建设方案
一、系统概述 物联网智慧安防实训综合实训基地是一个为学生提供综合实践、培养技能的场所,专注于物联网技术与智慧安防应用的培训和实训。通过物联网智慧安防实训综合实训基地的建设和运营,学生可以在真实的环境中进行实践训练,提高其物联网技…...
openGauss学习笔记-44 openGauss 高级数据管理-存储过程
文章目录 openGauss学习笔记-44 openGauss 高级数据管理-存储过程44.1 语法格式44.2 参数说明44.3 示例 openGauss学习笔记-44 openGauss 高级数据管理-存储过程 存储过程是能够完成特定功能的SQL语句集。用户可以进行反复调用,从而减少SQL语句的重复编写数量&…...
【Linux】进程信号篇Ⅲ:可重入函数、volatile关键字、SIGCHLD信号
信号Ⅲ 🔗 接上篇七、可重入函数八、volatile 关键字九、SIGCHLD 信号 🔗 接上篇 👉🔗进程信号篇Ⅰ:信号的产生(signal、kill、raise、abort、alarm)、信号的保存(core dump&#x…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...
