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…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...
