【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. 基本使用
- 添加依赖
<!-- 声明式事务依赖-->
<dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>6.0.6</version>
</dependency>
- 开启事务注解:
@EnableTransactionManagement
- 添加事务管理器到 IoC 容器中
/**
* 装配事务管理实现对象
* @param dataSource
* @return
*/
@Bean
public TransactionManager transactionManager(DataSource dataSource){return new DataSourceTransactionManager(dataSource);
}
- 在类上或方法上使用
@Transactional
- 在类上使用,则会影响到类中的每个方法同时,类级别标记的 @Transactional 注解中设置的事务属性也会延续影响到方法执行时的事务属性。除非在方法上又设置了 @Transactional 注解。对一个方法来说,离它最近的 @Transactional 注解中的事务属性设置生效。
4. 属性剖析
-
timeout
:默认 -1 ,表示永不超时,超时则会事务回滚 -
rollbackFor
:表示遇到属于该异常的类进行事务回滚,默认遇到 RuntimeException 及其子类和 Error 及其子类时才会回滚
,建议设置rollbackFor = Exception.class
或者Throwable.class
表示Exception及其子类
或Throwable
的异常都会触发回滚,同时不影响Error的回滚 -
propagation
:事务的传播行为,默认Propagation.REQUIRED
,一共有七种,一般只使用前两种事务传播行为类型 说明 REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见也是默认的选择。 REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。 SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。 MANDATORY 使用当前的事务,如果当前没有事务,就抛出异常。 NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。 NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与 REQUIRED
类似的操作 -
isolation
:用于设置事务的隔离级别,Isolation.DEFAULT
,一般不修改 -
readOnly
:默认 false,设置为 true 则只能做读操作,用于数据库针对查询优化,一般不使用
5. 声明式事务问题场景
5.1 事务不生效
- 未开启事务 :未使用开启事务注解
@EnableTransactionManagement
- 未被Spring管理 :被代理类需被Spring管理才能使用 AOP 功能
- 访问权限问题 :只有
public
权限修饰的方法才支持声明式事务 - 方法用
final
或static
修饰 :spring 事务底层用了 jdk 动态代理或者 cglib 生成代理类,这两个关键字将导致重写代理类的该方法 - 多线程调用 :不同线程获取到的数据库连接不一样,从而必然是两个不同的事务
- 表不支持事务 :数据库表引擎是
myisam
或其他不支持事务的引擎 - 方法内调用另一个同类方法:如下,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 方法不会生成事务。
修改方式:
- 新加一个 Service 将方法中挪到新的 Service 中,通过新 Service 调用
- 在该 Service 中注入自己,再将调用改为
userService.updateStatus(userModel)
- 使用
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 事务不回滚
- 错误的传播机制 :设置了
propagation = Propagation.NEVER
- try…catch…吞了异常:在 catch 中不抛出任何异常或抛了别的异常 spring 事务也不会回滚
- 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
模板的编程式事务的使用 :
- 注入
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);
}
- 注入到需要使用的类中,并使用如下两个方法之一
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();}}));
}
- 异常调用
status.setRollbackOnly()
方法进行回滚
相关文章:

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

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

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

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

掌握 Babel:让你的 JavaScript 与时俱进(上)
🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…...

Mysql进阶-InnoDB引擎事务原理及MVCC
事务原理 事务基础 事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系 统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。 事务的四大特性: 原子性(A…...

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

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

【经典LeetCode算法题目专栏分类】【第6期】二分查找系列:x的平方根、有效完全平方数、搜索二位矩阵、寻找旋转排序数组最小值
《博主简介》 小伙伴们好,我是阿旭。专注于人工智能AI、python、计算机视觉相关分享研究。 ✌更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~ 👍感谢小伙伴们点赞、关注! X的平方根 class Soluti…...
【大麦小米学量化】使用xtquant调用迅投MiniQMT客户端定时操作逆回购,再也不担心忘了赚零花钱了(含完整源代码)
文章目录 前言一、逆回购是什么?1. 什么是逆回购?2. 最低参与金额是多少?3. 逆回购交易是否安全?4. 逆回购交易适合什么类型的客户? 二、讯投XtQuant是什么?1. XtQuant运行依赖环境2. XtQuant运行逻辑 三、…...

php hyperf 读取redis,存储到数据库
背景说明 小白:伟哥,java中的set是无序的,Redis中可以带顺序吗? 伟哥:可以, 不过不叫set了,叫zset。 概述 SortedSet又叫zset,它是Redis提供的特殊数据类型,是一种特殊…...
云原生之深入解析K8S 1.27新特性如何简化状态服务跨集群平滑迁移
一、背景 Kubernetes v1.26 为 StatefulSet 引入了一个新的 Alpha 级别特性,可以控制 Pod 副本的序号。从 Kubernetes v1.27 开始,此特性进级到 Beta 阶段。序数可以从任意非负数开始, 那么该如何使用此功能呢?StatefulSet 序号为…...

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

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

分布式链路追踪 —— 基于Dubbo的traceId追踪传递
文章目录 原文链接RpcContext 上下文对象Dubbo 过滤器(Filter)对象基于Dubbo的traceId追踪传递实现 原文链接 RpcContext 上下文对象 在实现 Dubbo 调用之间的链路跟踪之前,先简单了解 RpcContext 上下文对象和 Filter 过滤器对象ÿ…...

【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命令,用于添加一个静态路由。具体含义如下࿱…...

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

4.配置系统时钟思路及方法
前言: 比起之前用过的三星的猎户座4412芯片,STM32F4的系统时钟可以说是小巫见大巫,首先我们需要清晰时钟产生的原理:几乎大多数的芯片都是由晶振产生一个比较低频的频率,然后通过若干个PLL得到单片机能承受的频率&…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...

云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...

如何应对敏捷转型中的团队阻力
应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...