Spring--spring事务在什么情况下会失效,以及对应的解决方案

前言

一般失效是使用了@Transaction注解的情况下,这篇博客就带你详解一下,哪些情况下注解会失效,在开发过程中要避免这些问题和可以及时发现这些问题,并且知道如何去规避和解决


一、Spring事务的基本原理

在深入了解事务失效的场景之前,我们先简单回顾一下Spring事务的工作原理:

  1. Spring通过AOP(面向切面编程)实现声明式事务
  2. 在方法执行前开启事务,执行后根据执行情况提交或回滚事务
  3. 默认情况下,Spring使用动态代理(JDK动态代理)SpringBoot2.x使用(CGLIB动态代理)来实现事务管理

    关于什么是AOP,什么是动态代理这篇博客可以带你深入理解


 

二、Spring事务失效的常见场景

2.1数据库引擎不支持事务

问题描述: 如果使用MySQL且存储引擎是MyISAM,由于MyISAM不支持事务,所以Spring事务会失效。

解决方案:

-- 查看表的存储引擎
SHOW CREATE TABLE table_name;-- 修改为支持事务的InnoDB引擎
ALTER TABLE table_name ENGINE=InnoDB;

 

2.2类没有被Spring管理

问题描述: 如果类没有加@Service@Component等注解,没有被Spring容器管理,事务自然不会生效。

错误示例:

// 没有Spring注解,不会被Spring管理
public class UserService {@Transactionalpublic void saveUser(User user) {// 事务不会生效}
}

正确示例:

@Service  // 加上Spring注解
public class UserService {@Transactionalpublic void saveUser(User user) {// 事务正常工作}
}

2.3方法不是public的

问题描述: @Transactional注解只能作用于public方法上,如果方法是private、protected或默认访问级别,事务将不会生效。

错误示例:

@Service
public class UserService {@Transactionalprivate void saveUser(User user) {  // private方法,事务失效userDao.save(user);}
}

正确示例:

@Service
public class UserService {@Transactionalpublic void saveUser(User user) {  // public方法,事务生效userDao.save(user);}
}

 

2.4同一个类中方法调用(自调用问题)

问题描述: 当同一个类中的一个方法调用另一个有事务的方法时,事务会失效。这是因为Spring的事务是基于AOP代理实现的,同一个类中的方法调用是通过this调用的,不会经过代理。

错误示例:

@Service
public class UserService {public void saveUserWithoutTransaction(User user) {// 直接调用本类的事务方法,事务不会生效this.saveUser(user);}@Transactionalpublic void saveUser(User user) {userDao.save(user);}
}

解决方案:

方案1:通过注入自身来调用

@Service
public class UserService {@Autowiredprivate UserService userService;public void saveUserWithoutTransaction(User user) {// 通过注入的代理对象调用userService.saveUser(user);}@Transactionalpublic void saveUser(User user) {userDao.save(user);}
}

2.5异常被catch没有抛出

问题描述: Spring事务默认只在遇到运行时异常(RuntimeException)和Error时才会回滚,如果异常被catch且没有重新抛出,事务不会回滚。

错误示例:

@Service
public class UserService {@Transactionalpublic void saveUser(User user) {try {userDao.save(user);// 可能抛出异常的操作throw new RuntimeException("保存失败");} catch (Exception e) {// 异常被捕获,没有重新抛出,事务不会回滚log.error("保存用户失败", e);}}
}

正确示例:

@Service
public class UserService {@Transactionalpublic void saveUser(User user) {try {userDao.save(user);// 可能抛出异常的操作} catch (Exception e) {log.error("保存用户失败", e);// 重新抛出异常,让事务回滚throw new RuntimeException("保存用户失败", e);}}
}

2.6抛出的异常类型不对

问题描述: 默认情况下,Spring只对RuntimeException和Error进行事务回滚,对于受检异常(checked exception)不会回滚。

错误示例:

@Service
public class UserService {@Transactionalpublic void saveUser(User user) throws Exception {userDao.save(user);// 抛出受检异常,事务不会回滚throw new Exception("保存失败");}
}

解决方案:

方案1:配置rollbackFor

@Service
public class UserService {@Transactional(rollbackFor = Exception.class)  // 指定所有异常都回滚public void saveUser(User user) throws Exception {userDao.save(user);throw new Exception("保存失败");  // 现在会回滚}
}

2.7多线程调用

问题描述: Spring事务是基于ThreadLocal实现的,不同线程之间的事务是独立的。在多线程环境下,子线程的事务和主线程的事务是分离的。

错误示例:

@Service
public class UserService {@Transactionalpublic void saveUsersAsync(List<User> users) {users.forEach(user -> {// 新线程中执行,不在当前事务中new Thread(() -> {userDao.save(user);  // 这个操作不在事务中}).start();});}
}

解决方案:

@Service
public class UserService {@Autowiredprivate TransactionTemplate transactionTemplate;public void saveUsersAsync(List<User> users) {users.forEach(user -> {new Thread(() -> {// 在新线程中手动管理事务transactionTemplate.execute(status -> {try {userDao.save(user);return true;} catch (Exception e) {status.setRollbackOnly();return false;}});}).start();});}
}

 

三、总结

Spring事务失效的原因主要包括:

  1. 环境问题:数据库不支持事务、Spring配置错误
  2. 代理问题:自调用、非public方法
  3. 异常处理问题:异常被捕获、异常类型不匹配
  4. 事务属性问题:传播行为设置错误
  5. 并发问题:多线程环境下的事务隔离

在使用Spring事务时,我们需要:

  • 理解Spring AOP的原理和限制
  • 正确配置事务管理器
  • 合理处理异常
  • 注意方法的访问级别和调用方式
  • 在多线程环境下特别小心

 

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

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

相关文章

在智慧教育行业中,OPS插拔式电脑启到什么作用

在全球数字化浪潮的推动下&#xff0c;教育行业正经历前所未有的深刻变革。目前&#xff0c;智慧校园已不再是简单的信息化升级&#xff0c;而是涵盖AI、云计算、大数据、物联网等技术的系统性创新。而作为智慧教育发展的助手之一——国产OPS插拔式电脑&#xff0c;能助力传统教…

Windows 配置 Qt 环境变量全指南

Windows 配置 Qt 环境变量全指南 适用于 Qt 5.x / 6.x, MSVC / MinGW, Qt Creator / CLion / CMake GUI 等环境 一. 为什么需要配置 Qt 环境变量 Qt 是一个跨平台 C 开发框架&#xff0c;包含 GUI、网络、SQL、多媒体等模块&#xff0c;安装后自带丰富工具链&#xff0c;如&am…

SpringBoot项目快速开发框架JeecgBoot——项目简介及系统架构!

项目简介及系统架构 Jeecg Boot是一款基于Spring Boot的开发平台&#xff0c;它采用前后端分离架构&#xff0c;集成的框架有Spring Boot 2.x、Spring Cloud、Ant Design of Vue、Mybatis-plus、Shiro和JWT&#xff0c;而且它支持微服务开发。Jeecg Boot还有强大的代码生成功能…

工业设计软件的范式革命:对象模型与五维市场驱动的未来

工业设计软件的技术洗牌本质 破局关键:万物对象模型的应用 工业设计的对象化重构 class IndustrialDesignObject:def __init__(self, obj_type, attributes):self.metadata = {"type": obj_type,"version": "1.0","entropy_rating"…

VMware 安装Windows 虚拟机,Windows 虚拟机可 ping 通本地电脑,但本地电脑无法 ping 通虚拟机 IP 的解决思路和操作步骤

VMware 安装Windows 虚拟机&#xff0c;Windows 虚拟机可 ping 通本地电脑&#xff0c;但本地电脑无法 ping 通虚拟机 IP 的问题如下图所示&#xff1a; 解决办法&#xff1a; 一、网络连接模式与网段一致性 确认虚拟机网络模式 若用 VMware 等软件&#xff0c;常见模式有 NA…

高精度RTK定位导航模块软硬件协同设计

高精度RTK定位导航模块软硬件协同设计 下载链接:摘要1.1 RTK技术背景与发展现状1.1.1 RTK技术原理与背景1.1.2 技术发展里程碑1.1.3 当前技术挑战与突破1.1.4 应用场景扩展1.1.5 标准化进展1.2.1 高精度定位的计算瓶颈1.2.2 功耗优化需求1.2.3 系统可靠性与实时性保障1.2.4 典型…

【软考高级系统架构论文】论多源数据集成及应用

论文真题 在如今信息爆炸的时代,企业、组织和个人面临着大量的数据。这些数据来自不同的渠道和资源,包括传感器、社交媒体、销售记录等,它们各自具有不同的数据格式、分布和存储方式。因此如何收集、整理和清洗数据,以建立一个一致、完整的数据集尤为重要。多源数据集成可…

如何将这些 SQL 插入语句批量执行?

要批量执行这些SQL插入语句&#xff0c;可根据使用的数据库管理系统(DBMS)选择不同的方法。以下是几种常见的批量执行方式&#xff1a; 1. 使用数据库客户端工具 MySQL / MariaDB 命令行&#xff1a;将所有SQL语句保存到文件(如cities.sql)&#xff0c;然后执行&#xff1a; 登…

RedisVL EmbeddingsCache深度实践与最佳指南

一、为什么需要 EmbeddingsCache 减少重复计算 对同一段文本&#xff0c;向量化模型会每次返回相同的嵌入。借助缓存&#xff0c;首次计算后无论后续何时再请求&#xff0c;都能直接复用上次结果。 降低业务延迟 嵌入模型推理耗时&#xff08;数十毫秒到百毫秒不等&#xff09…

Docker Compose 与 Harbor 私有仓库

目录 简介 一、Docker 容器重启策略与状态码解析 &#xff08;一&#xff09;Docker 容器重启策略详解 &#xff08;二&#xff09;Docker 容器常见退出状态码 二、Docker Compose 工具深度应用 &#xff08;一&#xff09;Docker Compose 简介与安装 &#xff08;二&am…

thinkphp8之文件上传

文件上传安装 命令&#xff1a;composer require topthink/think-filesystem 二&#xff0e;上传代码、接收代码 <form action"/index/index/index" enctype"multipart/form-data" method"post"> <input type"file" name…

【商业分析】价值流图应用案例:服务器硬件生产

在当今竞争激烈的市场环境下&#xff0c;服务器硬件制造商面临着诸多挑战。本文中&#xff0c;田辛老师将深入探讨价值流图&#xff08;VSM&#xff09;在某服务器硬件生产中的应用案例&#xff0c;展示其如何助力企业实现降本增效。 一、价值流图概述 &#xff08;一&#x…

系统性能优化-4 磁盘

系统性能优化-4 磁盘 磁盘作为计算机中速度最慢的硬件之一&#xff0c;常常是系统的性能瓶颈&#xff0c;优化磁盘一般能得到明显的提升~ 文章以如何高效的传输文件来讨论针对磁盘的优化技术&#xff0c;如零拷贝、直接 IO、异步 IO等。 最简单的网络传输 最简单的方式的当然…

Windows注册HTTP服务实现Jenkins Allure报告、测试日志永久访问

使用 NSSM (Non-Sucking Service Manager) 将 Allure 报告的 HTTP 服务注册为 Windows 后台服务的详细操作攻略&#xff0c;确保 Jenkins 测试结果可以长期通过 URL 访问。 ✅ 目标 将 allure generate 生成的报告目录托管为静态网页服务&#xff0c;并作为后台服务运行&#…

从ADI与AMD的专利诉讼,看高端FPGA的巅峰对决

RFSoC,作为FPGA家族中的“贵族”,高端芯片中的尖端代表,技术积累要求高、利润厚,售价贵,主要面向不差钱的军用雷达处理、通信和测试/测量仪器用户。 2019年,模拟芯片龙头ADI公司,发起专利侵权诉讼,而尝到甜头的赛灵思,一边反诉,一边揶揄ADI公司:爱哭的娃未必有奶吃…

性能测试-jmeter实战3

课程&#xff1a;B站大学 记录软件测试-性能测试学习历程、掌握前端性能测试、后端性能测试、服务端性能测试的你才是一个专业的软件测试工程师 性能测试-jmeter实战3 负载测试稳定性测试负载测试曲线图其他测试策略并发测试压力测试容量测试 性能指标的介绍响应时间并发用户数…

Maven镜像

在 Maven 中配置多个镜像源&#xff0c;主要是为了解决依赖包在不同地区下载速度不同的问题&#xff0c;或者为了使用特定的私有仓库作为依赖源。Maven 支持在 pom.xml 文件中配置多个镜像源&#xff08;repositories&#xff09;&#xff0c;也可以在 Maven 的全局配置文件 se…

ArduPilot 教程(2):运行第一个 SITL 无人机仿真

目录 1. MAVLink 通信协议 2. MAVProxy 地面控制站 3. 运行 SITL 无人机仿真 3.1. 使用 MAVProxy 控制无人机 3.2. 使用 SITL 地图界面控制无人机 4. MAVProxy 常用命令 5. 其它地面控制站 5.1. QGroundControl 5.2. MissionPlanner 5.3. 不启用 MAVProxy 6. 本讲小…

开源AI大模型驱动下视频媒介对图文生态的重构与S2B2C商业场景创新——基于AI智能名片与商城小程序源码的实践分析

摘要&#xff1a;数字媒介演进的进程中&#xff0c;视频对图片及文字的媒介侵蚀效应正呈现加速态势&#xff0c;尤其在Z世代及新网民群体中&#xff0c;视频已成为其触网的首要信息载体。本文基于媒介技术迭代与商业场景融合的双重视角&#xff0c;探究开源AI大模型如何通过智能…

Kafka线上集群部署方案:从环境选型到资源规划思考

在分布式消息系统的落地应用中&#xff0c;Kafka集群的线上部署方案直接关系到业务系统的稳定性与性能表现。不同于测试环境的简易搭建&#xff0c;生产级集群需要从操作系统适配、存储介质选型、容量规划到网络资源调度等多维度进行系统性设计。本文将从工程实践角度&#xff…