Springboot @Transactional使用时需注意的几个问题
一、事务的隔离级别
在Springboot应用中,如果我们想实现方法一旦执行有异常产生,就触发事务回滚,可以在方法上面添加@Transactional注解。如果应用采用mysql数据库,虽然mysql本身也有事务隔离机制,但在Sping+数据库的应用中,会以Spring事务为准。mysql定义的事务隔离级别为可重复读,在使用 Spring Boot 和 MySQL 的组合时,如果你不特别指定隔离级别,那么实际使用的将是 MySQL 的默认值 REPEATABLE READ。如果在一些特定场景中不想使用可重复读,可通过@Transactional注解的isolation属性来指定。isolation支持的选项有:
- ISOLATION_DEFAULT:使用后端数据库默认的隔离级别。
- ISOLATION_READ_UNCOMMITTED:最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、不可重复读或幻读。
- ISOLATION_READ_COMMITTED:允许读取已经提交的数据,可以防止脏读,但可能会出现不可重复读或幻读。
- ISOLATION_REPEATABLE_READ:对同一字段的多次读取结果是一致的,除非数据是被当前事务本身所修改,可以防止脏读和不可重复读,但幻读仍可能发生。
- ISOLATION_SERIALIZABLE:最高的隔离级别,完全服从 ACID 的隔离级别,所有的事务依次逐个执行,可以防止脏读、不可重复读以及幻读。
使用示例:
@Transactional(isolation = Isolation.READ_COMMITTED)
public void performTransaction() {
// 业务逻辑代码
}
二、事务的传播行为
事务的传播行为是指当一个事务方法被另一个事务方法调用时,两者之间的事务应该如何关联。通过配置不同的传播行为,可以控制是否应该创建新的事务、加入现有事务或者以非事务方式执行等。
Spring 提供了七种标准的事务传播行为,它们可以通过 @Transactional 注解的 propagation 属性来指定。以下是这些传播行为的详细说明:
PROPAGATION_REQUIRED (默认):
如果当前存在事务,则加入该事务;如果不存在,则创建一个新的事务。
这是最常用的传播行为,适用于大多数场景。
PROPAGATION_SUPPORTS
如果当前存在事务,则加入该事务;如果不存在,则以非事务方式执行。
适合那些对事务性没有特别要求的操作,如查询操作。
PROPAGATION_MANDATORY:
如果当前存在事务,则加入该事务;如果不存在,则抛出异常(IllegalTransactionStateException)。
用于强制要求在已有事务中执行的方法。
PROPAGATION_REQUIRES_NEW:
创建一个新的事务,如果当前存在事务,则将当前事务挂起。
适用于需要独立于外部事务执行的业务逻辑,确保内部操作不会影响外部事务的结果。
PROPAGATION_NOT_SUPPORTED:
以非事务方式执行操作,如果当前存在事务,则将当前事务挂起。
适合那些明确不需要事务的操作,如读取系统配置或发送邮件等。
PROPAGATION_NEVER:
以非事务方式执行,如果当前存在事务,则抛出异常(IllegalTransactionStateException)。
用于严格禁止在事务环境中执行的方法。
PROPAGATION_NESTED:
如果当前存在事务,则在嵌套事务内执行;如果不存在,则创建一个新的事务。
嵌套事务是外部事务的一部分,但可以独立于外部事务进行提交或回滚。这种传播行为依赖于底层数据库和驱动的支持,例如 MySQL 的 InnoDB 引擎支持保存点(SAVEPOINT),从而实现嵌套事务。
注意事项
性能考虑:选择合适的传播行为对于性能优化非常重要。例如,PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NOT_SUPPORTED 都会涉及到事务的挂起和恢复,这可能会带来额外的开销。
事务边界:正确理解事务的边界以及传播行为的影响,有助于避免潜在的问题,如死锁、数据不一致等。
嵌套事务支持:不是所有的数据库都支持嵌套事务。使用 PROPAGATION_NESTED 时,请确保你的数据库和驱动程序支持这一特性。
根据应用的具体需求选择适当的传播行为,可以帮助你更好地管理事务,确保数据的一致性和完整性。
三、Spring事务中存在的坑
在同一个类里面,编写两个方法,内部调用的时候,会导致事务设置失效。原因是没有用到
代理对象的缘故。具体来说:
Spring 使用 AOP 来实现事务管理,它会为每个带有 @Transactional 注解的方法创建一个代理对象。当你通过 Spring 容器获取这个类的实例并调用其方法时,实际上是调用了代理对象的方法,而不是原始类的方法。代理对象负责在方法调用前后插入事务管理逻辑。
然而,当你在一个类的非静态方法中直接调用另一个 @Transactional 方法时,调用并没有经过代理对象,而是直接调用了原始类的方法。因此,事务管理逻辑不会被应用,导致事务设置失效。
方法1:
1)、导入spring-boot-starter-aop依赖
2)、启动类添加注解@EnableAspectJAutoProxy(exposeProxy=true)
3)、事务使用的地方使用AopContext.currentProxy() 调用方法。
使用示例:
import org.springframework.aop.framework.AopContext;@Service
public class MyService {@Transactionalpublic void transactionalMethod() {// 事务逻辑}public void performOperation() {// 业务逻辑((MyService) AopContext.currentProxy()).transactionalMethod();}
}
不过这种方式使得代码更加复杂且不直观,因此尽量避免使用,除非绝对必要。
最推荐的做法是将事务方法移到不同的类中。这样可以确保每次调用事务方法时都通过代理对象进行,从而保证事务管理生效。具体可参考方法2:
方法2:
@Service
public class MyService {@Autowiredprivate AnotherService anotherService;public void performOperation() {// 业务逻辑anotherService.transactionalMethod();}
}@Service
public class AnotherService {@Transactionalpublic void transactionalMethod() {// 事务逻辑}
}
拓展:@Transactional支持的配置属性大盘点
除了上面提到的propagation和isolation,@Transactional 注解里边还支持配置以下属性:
1. value 或 transactionManager
- 作用:指定要使用的事务管理器的名称。如果你的应用程序中有多个事务管理器(例如,针对不同的数据源),你可以使用这个属性来明确指定哪一个事务管理器应该管理当前方法的事务。
- 默认值:
"transactionManager"
,这是 Spring 默认的事务管理器 Bean 名称。
@Transactional("myTransactionManager")
public void myTransactionalMethod() { // 业务逻辑 }
2. readOnly
- 作用:指定事务是否为只读事务。只读事务通常用于查询操作,可以提高性能(例如,禁用脏页写入等)。
- 取值:
false
(默认):事务不是只读的,允许进行插入、更新和删除操作。true
:事务是只读的,仅允许查询操作。
@Transactional(readOnly = true)
public List<Entity> findAllEntities() { // 查询操作 }
3. timeout
作用:定义事务的超时时间(单位为秒)。如果事务在指定时间内未能完成,Spring 会自动回滚事务。
默认值:-1,表示使用后端数据库或事务管理器的默认超时设置。
@Transactional(timeout = 30)
public void longRunningOperation() { // 长时间运行的业务逻辑 }
4. rollbackFor
作用:指定哪些异常应该触发事务回滚。默认情况下,只有未检查异常(如 RuntimeException 及其子类)会触发回滚。你可以通过这个属性指定其他异常类型也应触发回滚。
取值:一个或多个异常类,可以用逗号分隔。
@Transactional(rollbackFor = {CustomCheckedException.class, AnotherException.class}) public void methodThatMayThrowExceptions() { // 业务逻辑 }
5. noRollbackFor
作用:指定哪些异常不应该触发事务回滚。默认情况下,所有未检查异常都会触发回滚,但你可以通过这个属性指定某些异常不应触发回滚。
取值:一个或多个异常类,可以用逗号分隔。
@Transactional(noRollbackFor = CustomCheckedException.class)
public void methodThatMayThrowCustomException() { // 业务逻辑 }
6. validation
作用:指定是否在事务开始之前验证事务属性。如果设置为 true,Spring 会在事务开始前检查事务属性是否符合要求,如果不符则抛出异常。
默认值:false,即不进行验证。
@Transactional(validation = true)
public void validateTransactionalAttributes() { // 业务逻辑 }
相关文章:
Springboot @Transactional使用时需注意的几个问题
一、事务的隔离级别 在Springboot应用中,如果我们想实现方法一旦执行有异常产生,就触发事务回滚,可以在方法上面添加Transactional注解。如果应用采用mysql数据库,虽然mysql本身也有事务隔离机制,但在Sping数据库的应…...

数字经济下的 AR 眼镜
目录 1. 📂 AR 眼镜发展历史 1.1 AR 眼镜相关概念 1.2 市面主流 XR 眼镜 1.3 AR 眼镜大事记 1.4 国内外 XR 眼镜 1.5 国内 AR 眼镜四小龙 2. 🔱 关键技术 2.1 AR 眼镜近眼显示原理 2.2 AR 眼镜关键技术 2.3 AR 眼镜技术难点 3. Ὂ…...
力扣150题
88. 合并两个有序数组 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。 **注意:**…...
剑指offer搜索二维矩阵
题目连接 https://leetcode.cn/problems/search-a-2d-matrix-ii/’ 代码 自己想出来的 解法一 初始化两个指针,i0,j列数-1 若此时matrix[i][j]target 则返回true 若此时matrix[i][j]>target,表明在第j列中不可能存在target,因为列是升序的 若此时ma…...
如何设置浏览器不缓存网页
设置浏览器不缓存网页可以通过多种方法实现,以下是一些常见的策略: HTTP响应头控制: Cache-Control:这是最常用的HTTP头之一,用于控制响应的缓存行为。例如: Cache-Control: no-cache, no-store, must-r…...

Iris简单实现Go web服务器
package mainimport ("github.com/kataras/iris" )func main() {app : iris.New() // 实例一个iris对象//配置路由app.Get("/", func(ctx iris.Context) {ctx.WriteString("Hello Iris")})app.Get("/aa", func(ctx iris.Context) {ct…...
后端项目java中字符串、集合、日期时间常用方法
我这里只介绍了项目中最常用的哈,比如像集合有很多,但我们最常用的就是ArrayList。 然后我这里会以javascript中的字符串、数组的方法为基准来实现,有些方法js和java会有些区别也会介绍 字符串 每次修改 String 对象都会创建一个新的对象,而 StringBuffer 可以在同一个对象…...

【Spring事务】深入浅出Spring事务从原理到源码
什么是事务 保证业务操作完整性的一种数据库机制 (driver 驱动)事务特定 ACID A 原子性 (多次操作 要不一起成功 要不一起失败 (部分失败 savepoint)) C 一致性 (事务开始时数据状态,…...
vue.js滑动到顶便锁定位置
<template><div><div class"nav"></div><div class"searchBar" id"searchBar"><ul :class"searchBarFixed true ? isFixed :"> <li>区域<i class"iconfont icon-jiantouxia"…...

EdgeX Core Service 核心服务之 Core Command 命令
EdgeX Core Service 核心服务之 Core Command 命令 一、概述 Core-command(通常称为命令和控制微服务)可以代表以下角色向设备和传感器发出命令或动作: EdgeX Foundry中的其他微服务(例如,本地边缘分析或规则引擎微服务)EdgeX Foundry与同一系统上可能存在的其他应用程序…...
掌握常用HTML标签:创建个人简介网页
任务目标 理解HTML文档的基本结构,掌握常见的HTML标签及其用途,创建一个简单的个人简介网页。 学习内容脑图 #mermaid-svg-5GTdqH41gawr4v0h {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
音视频学习(二十五):ts
TS(MPEG-TS,MPEG Transport Stream) 是一种广泛应用于流媒体传输和存储的容器格式。它最早由 MPEG(Moving Picture Experts Group)组织制定,用于视频和音频的压缩编码。在 HLS(HTTP Live Stream…...

10. 虚拟机VMware Workstation Pro下共享Ubuntu和Win11文件夹
本文记录当前最新版虚拟机VMware Workstation Pro(2024.12)如何在win11下共享文件,以实现Windows与Ubuntu互传文件的目的。 1. 创建共享文件夹 1.1 先关闭虚拟机的客户机,打开虚拟机设置 1.2 在虚拟机设置界面找到“选项”->“…...
单元测试mock框架Mockito
为了继续改进 Mockito 并进一步改善单元测试体验,我们希望您升级到 2.1.0!Mockito 遵循语义版本控制,仅在主要版本升级时包含重大更改。在库的生命周期中,重大更改是推出一组全新功能所必需的,这些功能会改变现有行为甚…...

Python从0到100(七十八):神经网络--从0开始搭建全连接网络和CNN网络
前言: 零基础学Python:Python从0到100最新最全教程。 想做这件事情很久了,这次我更新了自己所写过的所有博客,汇集成了Python从0到100,共一百节课,帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…...

2024多模态大模型综述最新总结
摘要 随着人工智能技术的快速发展,多模态大模型(MLLM)已成为研究的新热点。这些模型以强大的大型语言模型(LLM)为基础,能够处理和理解多种模态信息,如文本、图像、视频和音频。本文综述了MLLM的…...
Redis——缓存穿透
文章目录 1. 问题介绍1.1 定义1.2 举例 2. 解决方案2.1 方案一:空值缓存2.1.1 做法2.1.2 举例2.1.3 示例代码2.1.4 优点2.1.5 缺点 2.2 方案二:布隆过滤器2.2.1 思想2.2.2 做法2.2.3 示例代码2.2.4 优点2.2.5 缺点 2.3 方案三:限流3. 总结 1.…...

1.gitlab 服务器搭建流程
前提条件: 一、服务器硬件水平 搭建gitlab服务器最低配置要求2核4G,低于这个配置的服务器运行效果很差。 gitlab官网:https://about.gitlab.com/ 下载地址:gitlab/gitlab-ce - Packages packages.gitlab.com 本机ubuntu 二、安装依赖 su…...

McDonald‘s Event-Driven Architecture 麦当劳事件驱动架构
原文链接 1 mcdonalds-technical-blog/ 原文链接 2 mcdonalds-technical-blog/ 麦当劳在异步、事务性和分析性处理用例中使用跨技术栈的事件,包括移动订单进度跟踪和向客户发送营销通信(交易和促销)。 统一事件平台(unified eve…...

GTID详解
概念和组成 1,全局事务表示:global transaction identifiers 2, GTID和事务一一对应,并且全局唯一 3,一个GTID在一个服务器上只执行一次 4,mysql 5.6.5开始支持 组成 GTID server_uuid:transaction_id 如…...

Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...

现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...

分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...