在 Java 开发中,事务管理是保证数据一致性的核心机制,尤其是在 Spring 框架中,@Transactional注解的使用极大简化了事务配置。然而,在实际开发中,事务常常会因为一些细节问题而失效,导致数据异常。本文将详细解析 Java 事务失效的八大场景,每个场景都提供代码示例与对应的修复方案。

一、事务方法非 public 修饰

失效原理

Spring 的@Transactional注解默认只对public方法生效。这是因为 Spring AOP 在实现事务管理时,无论是 JDK 动态代理还是 CGLIB 代理,都无法对非 public 方法(private、protected、默认访问权限)进行有效的事务增强。

失效代码

java运行

@Service
public class UserService {// 非public方法,事务注解失效@Transactionalvoid updateUser(Long id) { userMapper.updateStatus(id, 1);}
}

修复方案

将事务方法修改为public访问权限。

修复后代码

java运行

@Service
public class UserService {// 修改为public方法,事务生效@Transactionalpublic void updateUser(Long id) { userMapper.updateStatus(id, 1);}
}

二、异常被捕获且未重新抛出

失效原理

Spring 事务默认仅在遇到未捕获的RuntimeExceptionError时触发回滚。如果方法内部使用try-catch捕获了异常且未重新抛出,事务管理器会认为没有异常发生,从而不会执行回滚操作。

失效代码

java运行

@Service
public class OrderService {@Transactionalpublic void createOrder(Order order) {try {orderMapper.insert(order);// 模拟异常int i = 1 / 0;} catch (Exception e) {// 捕获异常但未抛出,事务不会回滚log.error("创建订单失败", e);}}
}

修复方案

方案一:捕获异常后重新抛出
方案二:使用TransactionAspectSupport手动触发回滚

修复后代码(方案一)

java运行

@Service
public class OrderService {@Transactionalpublic void createOrder(Order order) {try {orderMapper.insert(order);// 模拟异常int i = 1 / 0;} catch (Exception e) {log.error("创建订单失败", e);// 重新抛出异常,触发事务回滚throw new RuntimeException("创建订单失败", e);}}
}

修复后代码(方案二)

java运行

@Service
public class OrderService {@Transactionalpublic void createOrder(Order order) {try {orderMapper.insert(order);// 模拟异常int i = 1 / 0;} catch (Exception e) {log.error("创建订单失败", e);// 手动触发事务回滚TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}}
}

三、错误配置 rollbackFor 属性

失效原理

@TransactionalrollbackFor属性用于指定需要回滚的异常类型,默认值为{RuntimeException.class, Error.class}。如果业务中抛出的是受检查异常(如IOExceptionSQLException),且未在rollbackFor中声明,事务不会回滚。

失效代码

java运行

@Service
public class FileService {// 未指定rollbackFor,受检查异常不会触发回滚@Transactionalpublic void importData(String filePath) throws IOException {// 读取文件(可能抛出IOException)FileReader reader = new FileReader(filePath);// 数据入库操作dataMapper.batchInsert(parseData(reader));}
}

修复方案

显式指定rollbackFor属性,包含需要回滚的异常类型。

修复后代码

java运行

@Service
public class FileService {// 显式指定rollbackFor包含IOException@Transactional(rollbackFor = {IOException.class, RuntimeException.class})public void importData(String filePath) throws IOException {FileReader reader = new FileReader(filePath);dataMapper.batchInsert(parseData(reader));}
}// 更通用的方式:捕获所有Exception
@Service
public class FileService {@Transactional(rollbackFor = Exception.class)public void importData(String filePath) throws IOException {// 业务逻辑不变}
}

四、事务传播机制配置不当

失效原理

Spring 事务的传播机制决定了事务方法之间的嵌套行为。若传播机制配置不合理(如使用NOT_SUPPORTEDSUPPORTS等),可能导致操作不在事务中执行。

失效代码

java运行

@Service
public class OrderService {@Autowiredprivate PaymentService paymentService;@Transactionalpublic void createOrder(Order order) {orderMapper.insert(order);// 调用支付服务(非事务方式执行)paymentService.processPayment(order.getId(), order.getAmount());}
}@Service
public class PaymentService {// 配置为非事务方式执行@Transactional(propagation = Propagation.NOT_SUPPORTED)public void processPayment(Long orderId, BigDecimal amount) {paymentMapper.insert(new Payment(orderId, amount));// 若此处发生异常,不会回滚}
}

修复方案

根据业务需求选择合适的传播机制,常用的是默认的REQUIRED(如果当前有事务则加入,否则创建新事务)。

修复后代码

java运行

@Service
public class PaymentService {// 使用默认传播机制REQUIRED@Transactionalpublic void processPayment(Long orderId, BigDecimal amount) {paymentMapper.insert(new Payment(orderId, amount));}
}

五、同类方法内部调用

失效原理

Spring 事务基于 AOP 代理实现,事务增强逻辑在代理对象中执行。若同一个类中的方法 A 调用方法 B(B 有@Transactional注解),由于调用未经过代理对象,方法 B 的事务注解会失效。

失效代码

java运行

@Service
public class UserService {// 方法A(无事务)调用方法B(有事务)public void updateUserInfo(Long id, String name, Integer age) {updateUserName(id, name);  // 内部调用,事务失效updateUserAge(id, age);    // 内部调用,事务失效}@Transactionalpublic void updateUserName(Long id, String name) {userMapper.updateName(id, name);}@Transactionalpublic void updateUserAge(Long id, Integer age) {userMapper.updateAge(id, age);}
}

修复方案

方案一:将方法拆分到不同的类中
方案二:通过AopContext获取代理对象调用

修复后代码(方案二)

java运行

// 1. 首先在启动类开启暴露代理
@SpringBootApplication
@EnableAspectJAutoProxy(exposeProxy = true)  // 关键配置
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}// 2. 在Service中通过代理对象调用
@Service
public class UserService {public void updateUserInfo(Long id, String name, Integer age) {// 通过AopContext获取代理对象UserService proxy = (UserService) AopContext.currentProxy();proxy.updateUserName(id, name);  // 代理对象调用,事务生效proxy.updateUserAge(id, age);    // 代理对象调用,事务生效}@Transactionalpublic void updateUserName(Long id, String name) {userMapper.updateName(id, name);}@Transactionalpublic void updateUserAge(Long id, Integer age) {userMapper.updateAge(id, age);}
}

六、数据库不支持事务

失效原理

事务最终依赖数据库支持。若使用的数据库引擎不支持事务(如 MySQL 的MyISAM引擎),即使代码中配置了事务,也无法生效。

失效场景

sql

-- 使用MyISAM引擎创建表,不支持事务
CREATE TABLE `user` (`id` bigint NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;

此时即使 Service 层配置了@Transactional,数据库操作也不会有事务保障。

修复方案

使用支持事务的数据库引擎(如 MySQL 的InnoDB)。

修复后代码

sql

-- 使用InnoDB引擎创建表,支持事务
CREATE TABLE `user` (`id` bigint NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

七、未被 Spring 容器管理

失效原理

若事务所在的类未被 Spring 容器扫描并实例化(如未加@Service@Component等注解),@Transactional注解会因没有代理对象而失效。

失效代码

java运行

// 未加@Service注解,未被Spring管理
public class ProductService {@Autowiredprivate ProductMapper productMapper;@Transactionalpublic void updateStock(Long productId, Integer quantity) {productMapper.decreaseStock(productId, quantity);}
}

修复方案

为类添加 Spring 注解(如@Service),确保其被 Spring 容器管理。

修复后代码

java运行

// 添加@Service注解,被Spring容器管理
@Service
public class ProductService {@Autowiredprivate ProductMapper productMapper;@Transactionalpublic void updateStock(Long productId, Integer quantity) {productMapper.decreaseStock(productId, quantity);}
}

八、多线程场景下的事务隔离

失效原理

在事务方法中启动新线程执行数据库操作时,新线程的操作不会纳入当前事务管理(线程间事务上下文独立)。即使主线程事务回滚,新线程的操作也可能已提交。

失效代码

java运行

@Service
public class BatchService {@Autowiredprivate UserMapper userMapper;@Autowiredprivate LogMapper logMapper;@Transactionalpublic void batchProcess(List<Long> userIds) {// 主线程操作userMapper.batchUpdateStatus(userIds, 1);// 新线程执行日志记录(不在当前事务中)new Thread(() -> {logMapper.insert(new Log("批量处理用户: " + userIds));}).start();}
}

修复方案

避免在事务方法中使用多线程执行数据库操作,或使用分布式事务协调机制。

修复后代码

java运行

@Service
public class BatchService {@Autowiredprivate UserMapper userMapper;@Autowiredprivate LogMapper logMapper;@Transactionalpublic void batchProcess(List<Long> userIds) {// 主线程操作userMapper.batchUpdateStatus(userIds, 1);// 同一事务中执行日志记录logMapper.insert(new Log("批量处理用户: " + userIds));}
}

总结

事务失效的核心原因通常与以下几点相关:

  • 代理机制限制(非 public 方法、同类内部调用)
  • 异常处理不当(捕获未抛出、未配置 rollbackFor)
  • 事务属性配置错误(传播机制不合理)
  • 基础环境问题(数据库不支持、未被 Spring 管理)
  • 并发场景下的事务隔离问题

在实际开发中,需结合业务场景合理配置事务属性,同时注意编码规范,避免上述陷阱,才能确保事务机制有效运行,保障数据一致性。

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

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

相关文章

【Coze搞钱实战】14. 抖音直播间自动回复机器人实战教程:三小时搭建智能客服,互动率提升150%(保姆级无代码指南)

摘要:抖音直播间高频问题重复回复、观众互动不及时是运营痛点。本文针对新手和进阶用户,提供无代码的自动回复机器人搭建方案:新手1小时完成基础配置(Coze+抖音对接),进阶用户通过促销倒计时、粉丝分层、热点借势三大策略提升互动率150%。方案基于某女装直播间实测数据(…

云计算核心知识梳理

云计算作为新一代信息技术的核心,其体系涵盖特点、定义、技术演进及分类等多个维度,以下是对相关知识的系统整合与解读。 一、云计算的核心特点 / 优势 云计算的优势围绕资源利用效率、服务灵活性和管理便捷性展开,具体可拆解为五大核心特性: 按需自助服务:用户无需人工干…

安卓13_ROM修改定制化-----安卓 13 系统 ROM 定制化与低版本系统的核心区别

安卓系统凭借其全球领先的市场占有率,开放特性为厂商和开发者提供了深度定制的空间,形成了丰富的ROM生态圈。从最初的安卓1.0到最新的安卓15,系统在功能、性能和安全方面不断迭代升级,同时也为ROM定制带来了新的机遇与挑战。特别是从安卓11开始,谷歌对系统架构和安全机制进…

【Java后端】Spring Boot 2.7.x 和 Swagger 3.0.x (springfox 3.x) 的兼容性问题

springfox 在 Spring Boot 2.6 开始就有很多兼容性 bug&#xff08;主要是 Spring MVC PathPatternParser 的引入&#xff09;&#xff0c;导致在 Spring Boot 2.6/2.7 里经常出现 无法启动 / 无法访问 swagger-ui.html 的情况。&#x1f50e; 问题原因Spring Boot 2.6 开始默认…

Vue3+ts使用oidc-client-ts

配置 OIDC 客户端 在项目中创建 authOptions 对象&#xff0c;定义 OIDC 认证所需的配置项&#xff1a; export const authOptions {authority: https://xxxxxxxxx/UserCenter, // 认证服务器 URLclient_id: xxxx, // 客户端 IDredirect_uri: http://localhost:3000/callbac…

从 “数据中转站“ 到 “边缘智能中枢“:区域网关的技术突围与开发范式重构

在物联网架构中,区域网关长期被视为 "边缘与云端的桥梁"—— 负责协议转换、数据转发、设备接入等基础功能。但随着边缘计算兴起与 AI 模型轻量化,区域网关正经历从 "被动转发" 到 "主动决策" 的范式跃迁。 本文将从开发视角拆解区域网关的三大…

Django全栈班v1.04 Python基础语法 20250913 早上

print 函数基本用法 print函数会自加换行符&#xff0c;一个print&#xff0c;会打印一行输出。 print("第一行") print("第二行") print("第三行")输出结果&#xff1a;print 输出多个值 一个print可以同时输出多个值&#xff0c;这多个值会在一…

面试鸭Java八股之Kafka

Kafka是什么&#xff1f;它的主要应用场景有哪些? Kafka是一种分布式流事件处理平台&#xff0c;最初由 LinkedIn 开发&#xff0c;现在是 Apache 基金会的一部分。它的核心功能主要包括消息队列、流处理和数据集成。Kafka以高吞吐量、低延迟、可扩展和高容错性著称。 Kafka…

ARM32平台Bus Error深度排查:从调用栈到硬件原理的完整拆解

ARM32平台Bus Error深度排查&#xff1a;从调用栈到硬件原理的完整拆解 在嵌入式开发中&#xff0c;Bus Error&#xff08;信号7&#xff09;是个容易让人头疼的问题——它不像SIGSEGV&#xff08;段错误&#xff09;那样直观&#xff0c;常与硬件内存布局、指针破坏等底层问题…

适合工业用的笔记本电脑

在工业领域&#xff0c;生产环境往往复杂多变&#xff0c;从高温、高湿的车间&#xff0c;到布满粉尘的矿山&#xff0c;再到震动频繁的施工现场&#xff0c;普通的笔记本电脑很难在这样的环境中稳定运行&#xff0c;而工业用笔记本电脑的诞生&#xff0c;完美地解决了这一难题…

在LINUX中常见的文件系统类型

常见文件系统类型对比表文件系统类型作用和特点主要使用场景优缺点ext4Linux标准文件系统&#xff0c;日志式&#xff0c;支持大文件和分区Linux根文件系统、/home、/var等主要分区优点&#xff1a;稳定成熟&#xff0c;支持大文件(16TB)&#xff0c;日志功能保证数据安全&…

Unity核心概念⑥:Time

一、Time的主要用途主要用于游戏中参与位移、记时、时间暂停等。二、时间缩放比例1.时间停止&#xff1a;Time.timeScale 0;2.回复正常&#xff1a;Time.timeScale 1;3.二倍速&#xff1a;Time.timeScale 2;三、帧间隔时间帧间隔时间是指最近的一帧用了多少时间。1.用途主要…

Node.js 模块化规范详解

在 Node.js 中&#xff0c;模块化是开发应用程序的核心概念&#xff0c;它使得代码可以按照功能模块进行分割&#xff0c;易于维护、复用和扩展。Node.js 支持两种模块化规范&#xff1a;CommonJS&#xff08;CJS&#xff09;&#xff1a;这是 Node.js 最初使用的模块化规范。E…

前端网络性能优化实践:从 HTTP 请求到 HTTPS 与 HTTP/2 升级

在前端性能优化体系中&#xff0c;服务端与网络层的优化是提升用户体验的关键环节。本文将围绕 HTTP 请求优化、Cookie 管理、服务器缓存配置、gzip 压缩、HTTPS 部署及 HTTP/2 升级等核心内容&#xff0c;系统拆解优化策略与实施方法&#xff0c;为团队技术分享提供完整的知识…

[数据结构——lesson8.树]

目录 引言 学习目标 1.树的概念及结构 1.1树的定义 1.2树的基本概念 1.3 树的表示 (1)双亲表示法 (2)孩子表示法 (3)左孩子右兄弟表示法 1.4 树在实际中的运用&#xff08;表示文件系统的目录树结构&#xff09; 结束语&#xff1a; 引言 之前我们学习了栈和队列数…

告别双系统——WSL2+UBUNTU在WIN上畅游LINUX

在Windows 11上配置WSL开发环境指南 最近换工作需要深入研究代码&#xff0c;发现WSL&#xff08;Windows Subsystem for Linux&#xff09;是微软为Windows开发者提供的强大工具&#xff0c;可以在Windows上直接运行Ubuntu子系统&#xff0c;无需双系统或虚拟机&#xff08;满…

Python爬虫实战:研究Ticks and spines模块,构建电商数据采集和分析系统

1. 引言 1.1 研究背景 在信息时代,互联网数据呈现爆炸式增长,涵盖社会、经济、文化等多个领域,具有极高的研究与应用价值。如何高效获取目标数据并进行深度分析,成为信息处理领域的重要课题。Python 凭借其丰富的库支持和简洁的语法,在数据爬取与分析领域得到广泛应用:…

前端基础 —— B / CSS基础

一、CSS 基础概述定义&#xff1a;层叠样式表&#xff08;Cascading Style Sheets&#xff09;作用&#xff1a;美化页面、实现样式与结构分离二、CSS 基本语法与引入方式1. 语法规范选择器 {一条/N条声明}选择器决定针对谁修改 (找谁) 声明决定修改啥. (干啥)<style> p…

智能农机无人驾驶作业套圈路径规划

国产轻量级桌面GIS软件Snaplayers实践&#xff1a;智能农机无人驾驶作业套圈路径规划1、选择地块角点坐标文件2、加载地块到地图中3、设置套圈作业路径规划参数4、生成套圈作业路径5、查看套圈路径6、查看套圈路径8、完成本算法已经在国内外等农场已经使用多年。Snaplayers研发…

Java Collection集合框架:体系、核心与选型

目录 一、集合框架的顶层设计&#xff1a;接口与层次 1. 两大核心接口&#xff1a;Collection 和 Map 2. Collection接口的三大派系 二、核心实现类详解 1. List家族实现 2. Set家族实现 3. Queue/Deque家族实现 PriorityQueue&#xff1a; ArrayDeque&#xff1a; 三…