Spring事务和事务传播机制(1)

前言🍭

❤️❤️❤️SSM专栏更新中,各位大佬觉得写得不错,支持一下,感谢了!❤️❤️❤️

Spring + Spring MVC + MyBatis_冷兮雪的博客-CSDN博客

在Spring框架中,事务管理是一种用于维护数据库操作的一致性和完整性的机制。Spring事务管理提供了灵活的方式来处理事务,包括事务的创建、提交、回滚以及事务的传播行为。

一、为什么需要事务?🍭

事务定义:

将一组操作封装成一个执行单元(封装到⼀起),要么全部成功,要么全部失败。

为什么要用事务?

比如转账分为两个操作:

第一步操作:A 账户 -100 元。

第二步操作:B 账户 +100 元。

如果没有事务,第一步执行成功了,第二步执行失败了,那么 A 账户平白无故的 100 元就“人间蒸 发”了。而如果使用事务就可以解决这个问题,让这⼀组操作要么⼀起成功,要么⼀起失败。

二、Spring 中事务的实现🍭

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

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

在开始讲解它们之前,咱们先来回顾事务在 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 具体执行细节如下图所

Spring事务、事务隔离级别、事务传播机制(spring事务的实现方式和原理以及隔离级别?) | 半码博客

三、事务隔离级别🍭

1、事务特性🍉

事务有4 ⼤特性(ACID),原子性、持久性、⼀致性和隔离性,具体概念如下:

  • 原子性:⼀个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过⼀样。
  • ⼀致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
  • 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
  • 隔离性:数据库允许多个并发事务同时对其数据进⾏读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不⼀致。事务隔离分为不同级别,包括读未提交 (Read uncommitted)、读提交 (read committed)、可重复读 (repeatable read) 和串行化 (Serializable)。
上⾯ 4 个属性,可以简称为ACID。
原⼦性(Atomicity,或称不可分割性)
⼀致性(Consistency)
隔离性(Isolation,⼜称独立性)
持久性(Durability)。

而这 4 种特性中,只有隔离性(隔离级别)是可以设置的。

为什么要设置事务的隔离级别?
设置事务的隔离级别是用来保障多个并发事务执行更可控,更符合操作者预期的。
什么是可控呢?
比如近几年比较严重的新冠病毒,我们会把直接接触到确证病例的人员隔离到酒店,而把间接接触者(和直接接触着但未确诊的人)隔离在自己的家中,也就是针对不同的人群,采取不同的隔离级别,这种隔离方式就和事务的隔离级别类似,都是采取某种行动让某个事件变的“更可控”。而事务的隔离级别就是为了防止,其他的事务影响当前事务执行的一种策略。

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

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

相关文章

pdf 转 word

pdf 转 word 一、思路 直接调用LibreOffice 命令进行文档转换的命令行工具 使用的前系统中必须已经安装了 libreofficelibreoffice已翻译的用户界面语言包: 中文 (简体)libreoffice离线帮助文档: 中文 (简体)上传字体 重点:重点:重点: 亲…

idea使用docker生成镜像(打包镜像,导入镜像,导出镜像)

1:先下载安装dockerdesktop,安装成功后 2: 在cmd执行docker -v,查看安装的docker版本 C:\Users\dell>docker -v Docker version 24.0.5, build ced09963:需要启动 dockerdesktop应用,才算启动docker&a…

Global Illumination_Exponential Variance Shadow Maps(EVSM)

最近工程中需要集成高质量阴影(效率、效果),介于项目非循环渲染所以CSM无法使用,但动态建模中还需要快速增删改场景,阴影还必须重新生成,奈何之前简单SMPCF无法满足效率、效果要求,于是调研RVT等…

mysql数据传输到mssql

一、找开Navicat Premium 12 此时目标数据库会创建一个同名的表

深度学习环境配置教程(保姆教程)

深度学习环境配置教程(保姆教程) 目录1.Anaconda安装2.Anaconda环境操作相关1.显示所有环境2.新建虚拟环境3.激活虚拟环境4.在对应的虚拟环境中安装库(tensorflow与torch的安装)1. Tensorflow的CPU与GPU安装示例如下:2. pytorch的…

(七)Unity VR项目升级至Vision Pro需要做的工作

Vision Pro 概述 定位为混合现实眼镜,对AR支持更友好 无手柄,支持手(手势)、眼(注视)、语音交互 支持空间音频,相比立体声、环绕声更有沉浸感和空间感 支持VR/AR应用,支持多种应用模…

AWS复制EC2文件到S3,g4dn.2xlarge没有NVIDIA GPU 驱动问题

1、给instances权限 action > Security > modify IAM role 把提前创建好的role给这个instance即可 2、复制到bucket aws s3 cp gogo.tar.gz s3://ee547finalbucket不需要手动安装GPU驱动 如果要自己安装,参考https://docs.aws.amazon.com/AWSEC2/latest/U…

八、Linux下,grep/wc/管道符/echo/重定向符/tail如何使用?

1、grep命令 (1)主要用于文件 (2)主要作用是“通过关键字,过滤文件行” (3)示例: 2、wc命令 (1)统计文件的行数、单词数等 (2)示例…

Ansys Zemax | 手机镜头设计 - 第 1 部分:光学设计

本文是 3 篇系列文章的一部分,该系列文章将讨论智能手机镜头模组设计的挑战,从概念、设计到制造和结构变形的分析。本文是三部分系列的第一部分,将专注于OpticStudio中镜头模组的设计、分析和可制造性评估。(联系我们获取文章附件…

基于Python的微博大数据舆情分析,舆论情感分析可视化系统,可作为Python毕业设计

运行效果图 基于Python的微博大数据舆情分析,舆论情感分析可视化系统 系统介绍 微博舆情分析系统,项目后端分爬虫模块、数据分析模块、数据存储模块、业务逻辑模块组成。 先后进行了数据获取和筛选存储,对存储后的数据库数据进行提取分析处…

C语言:深度学习知识储备

目录 数据类型 每种类型的大小是多少呢? 变量 变量的命名: 变量的分类: 变量的作用域和生命周期 作用域: 生命周期: 常量 字符串转义字符注释 字符串: 转义字符 操作符: 算术操作符…

SAP ME2L/ME2M/ME3M报表增强添加字段(包含:LMEREPI02、SE18:ES_BADI_ME_REPORTING)

ME2L、ME2M、ME3M这三个报表的字段增强,核心点都在同一个结构里 SE11:MEREP_OUTTAB_PURCHDOC 在这里加字段,如果要加的字段是EKKO、EKPO里的数据,直接加进去,啥都不用做,就完成了 如果要加的字段不在EKKO和EKPO这两个…

基于Echarts的大数据可视化模板:智慧门店管理

目录 引言智慧门店管理的重要性Echarts在智慧门店管理中的应用智慧门店概述定义智慧门店的概念和核心智慧门店的关键技术智慧门店的发展趋势与方向智慧门店管理的作用Echarts与大数据可视化Echarts库以及其在大数据可视化领域的应用优势开发过程和所选设计方案模板如何满足管理…

[保研/考研机试] KY43 全排列 北京大学复试上机题 C++实现

题目链接&#xff1a; 全排列https://www.nowcoder.com/share/jump/437195121692001512368 描述 给定一个由不同的小写字母组成的字符串&#xff0c;输出这个字符串的所有全排列。 我们假设对于小写字母有a < b < ... < y < z&#xff0c;而且给定的字符串中的字…

从零实战SLAM-第四课(相机成像及常用视觉传感器)

在七月算法报的班&#xff0c;老师讲的蛮好。好记性不如烂笔头&#xff0c;关键内容还是记录一下吧&#xff0c;课程入口&#xff0c;感兴趣的同学可以学习一下。 --------------------------------------------------------------------------------------------------------…

[保研/考研机试] 杨辉三角形 西北工业大学复试上机题 C++实现

题目描述 Time Limit: 1000 ms Memory Limit: 256 mb 输入n值&#xff0c;使用递归函数&#xff0c;求杨辉三角形中各个位置上的值。 输入描述: 一个大于等于2的整型数n 输出描述: 题目可能有多组不同的测试数据&#xff0c;对于每组输入数据&#xff0c; 按题目的要求输…

符号随机梯度下降算法SIGNSGD

考虑随机优化问题&#xff1a; 符号随机梯度下降(SIGNSGD)算法&#xff1a; 假设基础&#xff1a; 收敛定理&#xff1a; 联邦优化&#xff1a;

08-微信小程序视图层

08-微信小程序视图层 文章目录 视图层 ViewWXML数据绑定列表渲染条件渲染模板引用importimport 的作用域include WXSS尺寸单位样式导入内联样式选择器全局样式与局部样式 WXS注意事项页面渲染数据处理 视图层 View 框架的视图层由 WXML 与 WXSS 编写&#xff0c;由组件来进行…

国产32位单片机XL32F001,带1 路 12bit ADC,I2C、SPI、USART 等外设

XL32F001 系列单片机采用高性能的 32 位 ARM Cortex-M0内核&#xff0c;宽电压工作范围的 MCU。嵌入 24KbytesFlash 和 3Kbytes SRAM 存储器&#xff0c;最高工作频率 24MHz。包含多种不同封装类型多款产品。芯片集成 I2C、SPI、USART 等通讯外设&#xff0c;1 路 12bit ADC&am…

idea中Maven报错Unable to import maven project: See logs for details问题的解决方法

idea中Maven报错Unable to import maven project: See logs for details问题的解决方法。 在查看maven的环境配置和idea的maven配置后&#xff0c;发现是idea 2020版本和maven 3.9.3版本的兼容性问题。在更改为Idea自带的maven 3.6.1版本后问题解决&#xff0c;能成功下载jar包…