当前位置: 首页 > news >正文

【Spring】Spring 事务

Spring 事务

文章目录

  • Spring 事务
  • 1. 简介
  • 2. Spring事务管理器
  • 3. 基本使用
  • 4. 属性剖析
  • 5. 声明式事务问题场景
    • 5.1 事务不生效
    • 5.2 事务不回滚
    • 5.3 大事务问题
  • 6. 编程式事务

1. 简介

  • 编程式事务:指手动编写程序来管理事务,即通过编写代码的方式直接控制事务的提交和回滚。主要优点是灵活性高,可以按照自己的需求来控制事务的粒度、模式等等。但是,一般编写大量的事务控制代码容易出现问题,对代码的可读性和可维护性有一定影响。
  • 声明式事务:指使用注解或 XML 配置的方式来控制事务的提交和回滚。

下面除了第6节编程式事务,其他都是指声明式事务。

2. Spring事务管理器

Spring声明式事务对应依赖

  • spring-tx :包含声明式事务实现的基本规范(事务管理器规范接口和事务增强等等)
  • spring-jdbc :包含 DataSource 方式事务管理器实现类 DataSourceTransactionManager
  • spring-orm :包含其他持久层框架的事务管理器实现类例如:Hibernate/Jpa

Spring声明式事务对应事务管理器接口:

在这里插入图片描述

较常使用的事务管理器是 org.springframework.jdbc.datasource.DataSourceTransactionManager ,将来整合 JDBC方式、JdbcTemplate方式、Mybatis方式的事务实现

DataSourceTransactionManager类中的主要方法:

  • doBegin() :开启事务
  • doSuspend() :挂起事务
  • doResume() :恢复挂起的事务
  • doCommit():提交事务
  • doRollback() :回滚事务

3. 基本使用

  1. 添加依赖
<!-- 声明式事务依赖-->
<dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>6.0.6</version>
</dependency>
  1. 开启事务注解:@EnableTransactionManagement
  2. 添加事务管理器到 IoC 容器中
/**
* 装配事务管理实现对象
* @param dataSource
* @return
*/
@Bean
public TransactionManager transactionManager(DataSource dataSource){return new DataSourceTransactionManager(dataSource);
}
  1. 在类上或方法上使用 @Transactional
    • 在类上使用,则会影响到类中的每个方法同时,类级别标记的 @Transactional 注解中设置的事务属性也会延续影响到方法执行时的事务属性。除非在方法上又设置了 @Transactional 注解。对一个方法来说,离它最近的 @Transactional 注解中的事务属性设置生效。

4. 属性剖析

  1. timeout :默认 -1 ,表示永不超时,超时则会事务回滚

  2. rollbackFor :表示遇到属于该异常的类进行事务回滚,默认 遇到 RuntimeException 及其子类和 Error 及其子类时才会回滚 ,建议设置 rollbackFor = Exception.class 或者 Throwable.class 表示 Exception及其子类Throwable 的异常都会触发回滚,同时不影响Error的回滚

  3. propagation :事务的传播行为,默认 Propagation.REQUIRED ,一共有七种,一般只使用前两种

    事务传播行为类型说明
    REQUIRED如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见也是默认的选择。
    REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起。
    SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行。
    MANDATORY使用当前的事务,如果当前没有事务,就抛出异常。
    NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
    NEVER以非事务方式执行,如果当前存在事务,则抛出异常。
    NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与 REQUIRED 类似的操作
  4. isolation :用于设置事务的隔离级别, Isolation.DEFAULT ,一般不修改

  5. readOnly :默认 false,设置为 true 则只能做读操作,用于数据库针对查询优化,一般不使用

5. 声明式事务问题场景

5.1 事务不生效

  1. 未开启事务 :未使用开启事务注解 @EnableTransactionManagement
  2. 未被Spring管理 :被代理类需被Spring管理才能使用 AOP 功能
  3. 访问权限问题 :只有 public 权限修饰的方法才支持声明式事务
  4. 方法用 finalstatic 修饰 :spring 事务底层用了 jdk 动态代理或者 cglib 生成代理类,这两个关键字将导致重写代理类的该方法
  5. 多线程调用 :不同线程获取到的数据库连接不一样,从而必然是两个不同的事务
  6. 表不支持事务 :数据库表引擎是 myisam 或其他不支持事务的引擎
  7. 方法内调用另一个同类方法:如下,add方法中调用了事务方法 updateStatus()
@Service
public class UserService {@Autowiredprivate UserMapper userMapper;public void add(UserModel userModel) {userMapper.insertUser(userModel);updateStatus(userModel);}@Transactionalpublic void updateStatus(UserModel userModel) {doSameThing();}
}

updateStatus() 方法拥有事务的能力是因为 spring aop 生成代理了对象,但这种方式调用了 this 对象的方法,所以 updateStatus 方法不会生成事务。

修改方式:

  1. 新加一个 Service 将方法中挪到新的 Service 中,通过新 Service 调用
  2. 在该 Service 中注入自己,再将调用改为 userService.updateStatus(userModel)
  3. 使用 AopContext.currentProxy() 调用,即改为 ((UserService)AopContext.currentProxy()).updateStatus(userModel)推荐
@Service
public class UserService {@Autowiredprivate UserMapper userMapper;public void add(UserModel userModel) {userMapper.insertUser(userModel);((UserService)AopContext.currentProxy()).updateStatus(userModel)}@Transactionalpublic void updateStatus(UserModel userModel) {doSameThing();}
}

5.2 事务不回滚

  1. 错误的传播机制 :设置了 propagation = Propagation.NEVER
  2. try…catch…吞了异常:在 catch 中不抛出任何异常或抛了别的异常 spring 事务也不会回滚
  3. rollbackFor参数不合理 :当发生了不属于 rollbackFor 定义的异常类及其子类的异常时,事务将不会回滚

5.3 大事务问题

通常情况下,我们会在方法上加 @Transactional 注解,添加事务功能,比如:

@Transactional
public void add(UserModel userModel) throws Exception {query1();query2();query3();roleService.save(userModel);update(userModel);
}

@Transactional 注解,如果被加到方法上,有个缺点就是整个方法都包含在事务当中了。上面的这个例子中,在 UserService 类中,其实只有这两行才需要事务,但是这种写法会导致所有的 query() 方法也被包含在同一个事务中。如果 query 方法非常多,调用层级很深,而且有部分查询方法比较耗时的话,会造成整个事务非常耗时,而从造成大事务问题。

6. 编程式事务

5中所提到的问题都是声明式事务的,一般建议少使用声明式事务,但并不是说一定不能用它,如果项目中有些业务逻辑比较简单,而且不经常变动,使用 @Transactional 注解开启事务也无妨,因为它更简单,开发效率更高,但是千万要小心事务失效的问题。大项目更建议使用基于 TransactionTemplate 的编程式事务,即通过手动编写代码实现的事务。

基于 TransactionTemplate 模板的编程式事务的使用

  1. 注入 TransactionTemplate 模板到 IoC 容器中
@Bean
public DataSource dataSource() {DruidDataSource dataSource = new DruidDataSource();dataSource.setUsername(username);dataSource.setPassword(password);dataSource.setUrl(url);dataSource.setDriverClassName(driver);return dataSource;
}@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);
}@Bean
public TransactionTemplate transactionTemplate(PlatformTransactionManager platformTransactionManager) {return new TransactionTemplate(platformTransactionManager);
}
  1. 注入到需要使用的类中,并使用如下两个方法之一
    • execute(TransactionCallback<T> action)有返回值
    • executeWithoutResult(Consumer<TransactionStatus> action) 无返回值
@Autowize
private TransactionTemplate transactionTemplate;@Transactional
public void add(UserModel userModel) throws Exception {query1();query2();query3();transactionTemplate.executeWithoutResult((status -> {try {roleService.save(userModel);update(userModel);} catch (Exception e) {status.setRollbackOnly();}}));
}
  1. 异常调用 status.setRollbackOnly() 方法进行回滚

相关文章:

【Spring】Spring 事务

Spring 事务 文章目录 Spring 事务1. 简介2. Spring事务管理器3. 基本使用4. 属性剖析5. 声明式事务问题场景5.1 事务不生效5.2 事务不回滚5.3 大事务问题 6. 编程式事务 1. 简介 编程式事务&#xff1a;指手动编写程序来管理事务&#xff0c;即通过编写代码的方式直接控制事务…...

Ubuntu 虚拟机环境,编译AOSP源码

环境 : VMware虚拟机 Ubuntu 20.04.3 LTS 搭建配置开发环境 sudo apt-get install git-core gnupg flex bison build-essential zip curl zlib1g-dev gcc-multilib g-multilib libc6-dev-i386 libncurses5 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev libgl…...

2023.12.18杂记

今天特地搜了一下国内不错的博客网站&#xff0c;本来想在掘金上写的&#xff0c;但是怕被人喷&#xff08;&#xff0c;所以还是决定在csdn上写了哈哈哈。 这篇文章主要整理一下我今天写代码时遇到的疑惑以及记录一下思考过程吧。 第一个注意的地方&#xff0c;我们的get查询…...

智能优化算法应用:基于阿基米德优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于阿基米德优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于阿基米德优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.阿基米德优化算法4.实验参数设定…...

K8s内容器拓扑图工具

1.背景&#xff1a;随着线上容器越来越多&#xff0c;需要一个可视化的方式展示各个容器之间的拓扑图。 2.需求&#xff1a;轻量级&#xff0c;部署方便。 3.部署 helm repo add groundcover https://helm.groundcover.com/ helm repo update helm install caretta --namespa…...

掌握 Babel:让你的 JavaScript 与时俱进(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…...

Mysql进阶-InnoDB引擎事务原理及MVCC

事务原理 事务基础 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向系 统提交或撤销操作请求&#xff0c;即这些操作要么同时成功&#xff0c;要么同时失败。 事务的四大特性&#xff1a; 原子性&#xff08;A…...

「X」Embedding in NLP|神经网络和语言模型 Embedding 向量入门

在「X」Embedding in NLP 进阶系列中&#xff0c;我们介绍了自然语言处理的基础知识——自然语言中的 Token、N-gram 和词袋语言模型。今天&#xff0c;我们将继续和大家一起“修炼”&#xff0c;深入探讨神经网络语言模型&#xff0c;特别是循环神经网络&#xff0c;并简要了解…...

JVM-11-运行时栈帧结构

“栈帧”&#xff08;Stack Frame&#xff09;则是用于支持虚拟机进行方法调用和方法执行背后的数据结构&#xff0c;它也是虚拟机运行时数据区中的虚拟机栈&#xff08;Virtual MachineStack&#xff09;的栈元素。 栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回…...

【经典LeetCode算法题目专栏分类】【第6期】二分查找系列:x的平方根、有效完全平方数、搜索二位矩阵、寻找旋转排序数组最小值

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能AI、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; X的平方根 class Soluti…...

【大麦小米学量化】使用xtquant调用迅投MiniQMT客户端定时操作逆回购,再也不担心忘了赚零花钱了(含完整源代码)

文章目录 前言一、逆回购是什么&#xff1f;1. 什么是逆回购&#xff1f;2. 最低参与金额是多少&#xff1f;3. 逆回购交易是否安全&#xff1f;4. 逆回购交易适合什么类型的客户&#xff1f; 二、讯投XtQuant是什么&#xff1f;1. XtQuant运行依赖环境2. XtQuant运行逻辑 三、…...

php hyperf 读取redis,存储到数据库

背景说明 小白&#xff1a;伟哥&#xff0c;java中的set是无序的&#xff0c;Redis中可以带顺序吗&#xff1f; 伟哥&#xff1a;可以&#xff0c; 不过不叫set了&#xff0c;叫zset。 概述 SortedSet又叫zset&#xff0c;它是Redis提供的特殊数据类型&#xff0c;是一种特殊…...

云原生之深入解析K8S 1.27新特性如何简化状态服务跨集群平滑迁移

一、背景 Kubernetes v1.26 为 StatefulSet 引入了一个新的 Alpha 级别特性&#xff0c;可以控制 Pod 副本的序号。从 Kubernetes v1.27 开始&#xff0c;此特性进级到 Beta 阶段。序数可以从任意非负数开始&#xff0c; 那么该如何使用此功能呢&#xff1f;StatefulSet 序号为…...

鸿蒙OS:打破界限的操作系统新星

导言 鸿蒙OS&#xff08;HarmonyOS&#xff09;是华为公司为应对技术封锁而推出的分布式操作系统&#xff0c;其背后蕴含着华为构建全球数字生活愿景的雄心。本文将深入剖析鸿蒙OS的起源、核心特性&#xff0c;并展望其未来在数字生态中的角色。 1. 背景与起源 华为的…...

预测性维护在汽车制造行业中的应用

汽车制造行业是一个高度复杂和精细化的领域&#xff0c;依赖于各种设备来完成生产流程。这些设备包括机械装配线、焊接机器人、喷涂设备、传送带等。然而&#xff0c;这些设备在长时间运行中不可避免地会遇到各种故障&#xff0c;给生产进程带来延误和成本增加。为了应对这一挑…...

分布式链路追踪 —— 基于Dubbo的traceId追踪传递

文章目录 原文链接RpcContext 上下文对象Dubbo 过滤器&#xff08;Filter&#xff09;对象基于Dubbo的traceId追踪传递实现 原文链接 RpcContext 上下文对象 在实现 Dubbo 调用之间的链路跟踪之前&#xff0c;先简单了解 RpcContext 上下文对象和 Filter 过滤器对象&#xff…...

【uniapp小程序-上拉加载】

在需要上拉加载的页面的page.json上添加红框框里面的 onReachBottom() {if(this.commentCurrent<this.commentTotal){this.commentCurrent 1; this.commentList();this.status loading;}else{this.status ;} }, methods:{commentList(){let params {courseid:this.cour…...

ubuntu添加路由

ip route show 查看当前路由表 sudo ip route add /mask via 添加一条路由 目标ip 1.1.1.1/100 下一跳 2.2.2.2 sudo ip route add 1.1.1.1/100 via 2.2.2.2 dev ens160 proto static metric 100这是一条Linux命令&#xff0c;用于添加一个静态路由。具体含义如下&#xff1…...

python图像二值化处理

目录 1、双峰法 2、P参数法 3、迭代法 4、OTSU法 图像的二值化处理是将图像上的像素点的灰度值设置为0或255&#xff0c;也就是将整个图像呈现出明显的只有黑和白的视觉效果。二值化是图像分割的一种最简单的方法&#xff0c;可以把灰度图像转换成二值图像。具体实现是将大…...

4.配置系统时钟思路及方法

前言&#xff1a; 比起之前用过的三星的猎户座4412芯片&#xff0c;STM32F4的系统时钟可以说是小巫见大巫&#xff0c;首先我们需要清晰时钟产生的原理&#xff1a;几乎大多数的芯片都是由晶振产生一个比较低频的频率&#xff0c;然后通过若干个PLL得到单片机能承受的频率&…...

使用openMVS库,在VS2022中启用c++17标准编译仍然报错

使用openMVS库&#xff0c;在VS2022中启用c17标准编译仍然报错 现象 项目中引用了某些开源库&#xff08;例如openmvs2.1.0&#xff09;&#xff0c;编译时要求启用编译器对c17的支持。 没问题&#xff01;大家都知道在下图所示的位置调整C语言标准&#xff1a; 但是&#…...

uniGUI之上传文件UniFileUploadButton

TUniFileUploadButton主要属性&#xff1a; Filter: 文件类型过滤&#xff0c;有图片image/* audio/* video/*三种过滤 MaxAllowedSize: 设置文件最大上传尺寸&#xff1b; Message&#xff1a;标题以及消息文本&#xff0c;可翻译成中文 TUniFileUploadButton控件 支持多…...

福德植保无人机工厂:创新科技与绿色农业的完美结合

亲爱的读者们&#xff0c;欢迎来到福德植保无人机工厂的世界。这里&#xff0c;科技与农业的完美结合为我们描绘出一幅未来农业的新篇章。福德植保无人机工厂作为行业的领军者&#xff0c;以其领先的无人机技术&#xff0c;创新的理念&#xff0c;为我们展示了一种全新的农业服…...

JsRpc技术服务搭建,最简单的JSRPC,Flask+undetected-chromedriver

只需10来行代码快速实现JSRpc&#xff0c;最简单的JSRPC 使用Flask和undetected-chromedriver快速实现JsRpc 推荐Python版本3.7.x及以上&#xff0c;需要pip安装 pip install Flask pip install undetected-chromedriver __author__ jiuLiang __email__ "jiuliangef…...

<优化接口设计的思路>:接口安全

前言 一、接口安全的方式   1. 身份认证&#xff0c;鉴别客户端   2. 请求过程鉴权&#xff0c;防止请求被篡改   3. 访问控制&#xff0c;即控制客户端对API的访问权限 前言 某家电商平台上&#xff0c;用户可以通过客户端发起购物请求&#xff0c;并对所选商品进行下…...

Gitee基础知识

目录 1-gitee 1.1gitee介绍 1.2git与gitee的关系 1.3在国内为什么选择Gitee 2-注册与创建远程仓库 2.1注册 2.2创建远程仓库 2.3配置ssh公钥 2.3.1公钥的生成方法&#xff1a; 2.3.2 在gitee中配置公钥 2.3.4验证公钥 3-添加与推送远程仓库master 3.1基本命令…...

网络空间搜索引擎- FOFA的使用技巧总结

简介 FOFA是一款网络空间测绘的搜索引擎&#xff0c;旨在帮助用户以搜索的方式查找公网上的互联网资产。 FOFA的查询方式类似于谷歌或百度&#xff0c;用户可以输入关键词来匹配包含该关键词的数据。不同的是&#xff0c;这些数据不仅包括像谷歌或百度一样的网页&#xff0c;还…...

用户行为分析遇到的问题-ubantu16,hadoop3.1.3

用户行为分析传送门 我的版本 ubantu16 hadoop 3.1.3 habse 2.2.2 hive3.1.3 zookeeper3.8.3 sqoop 1.46/1.47 我sqoop把MySQL数据往hbase导数据时候有问题 重磅&#xff1a;大数据课程实验案例&#xff1a;网站用户行为分析&#xff08;免费共享&#xff09; 用户行为分析-小…...

camera曝光时间

曝光和传感器读数 相机上的图像采集过程由两个不同的部分组成。第一部分是曝光。曝光完成后&#xff0c;第二步就是从传感器的寄存器中读取数据并传输&#xff08;readout&#xff09;。 曝光&#xff1a;曝光是图像传感器进行感光的一个过程&#xff0c;相机曝光时间&#xf…...

Vue 项目中使用 debugger 在 chrome 谷歌浏览器中失效以及 console.log 指向去了 vue.js 代码

问题 今天在代码里面输出 console.log 信息直接指向了 vue.js&#xff0c;并且代码里面写了 debgger 也不生效 解决 f12 找到浏览器的这个设置图标 找到这个 ignore list 的 custom exclusion rules 取消掉 /node_modules/|/bower_components/ 这样就正常了...