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

Spring事务失效的8个经典陷阱

Spring事务管理是企业级Java应用的核心功能看似简单的Transactional注解如果使用不当将会引发严重的生产问题比如因事务失效带来的数据不一致问题。事务失效往往不会抛出异常而是静默发生等到业务出现问题时才被发现造成严重的数据不一致。本文将分析8种导致Spring事务失效的使用问题并提供相应的解决方案。一、事务注解应用在非public方法上问题现象开发者在非public方法上添加Transactional注解但事务没有生效。Service public class UserService { Autowired private UserMapper userMapper; // 事务无效方法不是public的 Transactional protected void createUser(User user) { userMapper.insert(user); // 如果这里抛出异常数据不会回滚 } }原理分析Spring AOP的代理机制默认只拦截public方法。这是因为事务通知是基于Spring AOP实现的而Spring AOP默认只拦截public方法调用。查看AbstractFallbackTransactionAttributeSource类的源码可以发现// AbstractFallbackTransactionAttributeSource.java protected TransactionAttribute computeTransactionAttribute(Method method, Class? targetClass) { // Dont allow no-public methods as required. if (allowPublicMethodsOnly() !Modifier.isPublic(method.getModifiers())) { return null; } // ... }非public方法上的Transactional注解会被直接忽略返回null导致事务不生效。解决方案确保标注Transactional的方法为publicService public class UserService { Autowired private UserMapper userMapper; // 正确方法是public的 Transactional public void createUser(User user) { userMapper.insert(user); // 如果抛出异常数据会回滚 } }二、同一个类中方法调用问题现象在同一个类中非事务方法调用事务方法或者事务方法调用另一个具有不同事务属性的方法事务会失效。Service public class OrderService { public void createOrder(Order order) { // 直接调用同类中的事务方法 this.createOrderWithTransaction(order); // 如果createOrderWithTransaction方法抛出异常 // 事务不会回滚 } Transactional public void createOrderWithTransaction(Order order) { // 数据库操作... throw new RuntimeException(故意抛出异常); } }原理分析Spring事务基于动态代理实现当在同一个类中调用方法时是通过this引用调用的而不是通过代理对象。这导致事务切面无法拦截方法调用事务自然就失效了。简言之只有通过代理对象调用方法时Spring事务才会生效。解决方案有几种方法可以解决方法1使用自我注入typescriptService public class OrderService { Autowired private OrderService self; // 自我注入注入的是代理对象 public void createOrder(Order order) { // 通过代理对象调用事务方法 self.createOrderWithTransaction(order); // 如果createOrderWithTransaction方法抛出异常 // 事务会正常回滚 } Transactional public void createOrderWithTransaction(Order order) { // 数据库操作... throw new RuntimeException(故意抛出异常); } }方法2使用AopContext获取代理对象需要额外配置EnableAspectJAutoProxy(exposeProxy true) // 配置类上添加此注解 public class AppConfig { // ... } Service public class OrderService { public void createOrder(Order order) { // 通过AopContext获取代理对象 ((OrderService) AopContext.currentProxy()) .createOrderWithTransaction(order); // 事务会正常工作 } Transactional public void createOrderWithTransaction(Order order) { // 数据库操作... throw new RuntimeException(故意抛出异常); } }方法3将方法拆分到不同的类中Service public class OrderFacadeService { Autowired private TransactionalOrderService orderService; public void createOrder(Order order) { orderService.createOrderWithTransaction(order); // 事务会正常工作 } } Service public class TransactionalOrderService { Transactional public void createOrderWithTransaction(Order order) { // 数据库操作... throw new RuntimeException(故意抛出异常); } }三、异常被吞没问题现象开发者在事务方法中捕获了异常但没有重新抛出导致事务无法回滚。Service public class PaymentService { Autowired private PaymentMapper paymentMapper; Transactional public void processPayment(Payment payment) { try { paymentMapper.insert(payment); // 其他业务逻辑 throw new RuntimeException(支付处理失败); } catch (Exception e) { log.error(支付异常, e); // 错误捕获异常但未重新抛出事务不会回滚 } } }原理分析Spring事务管理器是通过异常触发回滚的。当方法执行过程中抛出异常并且这个异常满足回滚条件时事务管理器才会执行回滚操作。如果异常被捕获且没有重新抛出Spring事务管理器就不知道发生了异常自然不会回滚事务。解决方案有两种解决方法方法1重新抛出异常Service public class PaymentService { Autowired private PaymentMapper paymentMapper; Transactional public void processPayment(Payment payment) { try { paymentMapper.insert(payment); // 其他业务逻辑 throw new RuntimeException(支付处理失败); } catch (Exception e) { log.error(支付异常, e); // 正确重新抛出异常事务会回滚 throw e; // 或者抛出新的异常 } } }方法2使用TransactionAspectSupport手动回滚Service public class PaymentService { Autowired private PaymentMapper paymentMapper; Transactional public void processPayment(Payment payment) { try { paymentMapper.insert(payment); // 其他业务逻辑 throw new RuntimeException(支付处理失败); } catch (Exception e) { log.error(支付异常, e); // 正确手动标记事务回滚 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } } }四、异常类型不匹配回滚规则问题现象开发者抛出了异常但事务没有回滚。这通常是因为抛出的异常类型不满足默认的回滚规则。Service public class ReportService { Autowired private ReportMapper reportMapper; Transactional public void generateReport() { reportMapper.insertReportData(); // 其他业务逻辑 if (somethingWrong()) { // 抛出受检异常默认不会导致事务回滚 throw new IOException(报告生成失败); } } }原理分析Spring默认只在遇到未检查异常RuntimeException及其子类和Error时才回滚事务。受检异常如IOException、SQLException被认为是业务异常默认情况下不会触发事务回滚。这是因为Transactional注解的默认配置是Transactional(rollbackFor RuntimeException.class)解决方案有两种解决方法方法1指定回滚的异常类型Service public class ReportService { Autowired private ReportMapper reportMapper; // 正确指定回滚的异常类型包括IOException Transactional(rollbackFor {IOException.class}) public void generateReport() throws IOException { reportMapper.insertReportData(); // 其他业务逻辑 if (somethingWrong()) { throw new IOException(报告生成失败); // 现在会触发事务回滚 } } }方法2将受检异常转换为非受检异常Service public class ReportService { Autowired private ReportMapper reportMapper; Transactional public void generateReport() { reportMapper.insertReportData(); // 其他业务逻辑 try { if (somethingWrong()) { throw new IOException(报告生成失败); } } catch (IOException e) { // 将受检异常转换为非受检异常 throw new RuntimeException(报告生成失败, e); // 现在会触发事务回滚 } } }五、数据库不支持事务问题现象所有事务配置看起来都正确但事务仍然不生效。原理分析某些数据库引擎不支持事务功能。最常见的例子是MySQL的MyISAM引擎它不支持事务操作。如果表使用的是MyISAM引擎即使Spring事务配置正确也无法实现事务回滚。解决方案确保使用支持事务的数据库引擎对于MySQL使用InnoDB引擎而不是MyISAM检查表的创建语句确保引擎类型正确-- 检查表引擎 SHOW TABLE STATUS WHERE Name your_table_name; -- 修改表引擎为InnoDB ALTER TABLE your_table_name ENGINEInnoDB;六、错误的传播行为设置问题现象在嵌套事务场景中内部事务的回滚没有按照预期工作。Service public class OrderService { Autowired private PaymentService paymentService; Transactional public void createOrder(Order order) { // 保存订单 orderMapper.insert(order); try { // 调用支付服务 paymentService.processPayment(order.getPayment()); } catch (Exception e) { log.error(支付失败但订单已创建, e); // 处理支付失败逻辑但期望订单依然保存 } } } Service public class PaymentService { // 错误的传播行为会影响外部事务 Transactional(propagation Propagation.REQUIRED) public void processPayment(Payment payment) { paymentMapper.insert(payment); throw new RuntimeException(支付处理失败); } }原理分析Spring提供了不同的事务传播行为用于控制事务的边界。最常用的是REQUIRED默认值如果当前存在事务则加入该事务如果不存在则创建新事务REQUIRES_NEW创建新事务如果当前存在事务则挂起当前事务NESTED如果当前存在事务则创建嵌套事务如果不存在则等同于REQUIREDSUPPORTS如果当前存在事务则加入该事务如果不存在则以非事务方式执行使用不当的传播行为会导致事务范围不符合预期特别是在异常处理场景中。解决方案根据业务需求选择正确的传播行为Service public class OrderService { Autowired private PaymentService paymentService; Transactional public void createOrder(Order order) { // 保存订单 orderMapper.insert(order); try { // 调用支付服务 paymentService.processPayment(order.getPayment()); } catch (Exception e) { log.error(支付失败但订单已创建, e); // 处理支付失败逻辑但期望订单依然保存 } } } Service public class PaymentService { // 正确使用REQUIRES_NEW创建独立事务 Transactional(propagation Propagation.REQUIRES_NEW) public void processPayment(Payment payment) { paymentMapper.insert(payment); throw new RuntimeException(支付处理失败); // 只有支付事务会回滚不影响外部订单事务 } }传播行为选择指南如果希望内部方法的异常不影响外部事务使用REQUIRES_NEW如果希望内部方法的回滚不影响外部事务但共享同一连接使用NESTED注意这需要数据库支持保存点如果希望完全共享外部事务的命运使用REQUIRED七、未被Spring管理的类问题现象在类上添加了Transactional注解但事务没有生效。// 未被Spring容器管理 public class UserService { Autowired private UserMapper userMapper; Transactional public void createUser(User user) { userMapper.insert(user); throw new RuntimeException(测试); // 事务不会回滚 } }原理分析Spring事务是通过AOP实现的只有被Spring容器管理的Bean才能被代理进而应用事务切面。如果类没有被Spring正确识别为BeanTransactional注解就无法生效。常见的原因包括类上缺少Component、Service等注解类没有被组件扫描到类是通过new关键字直接创建的实例解决方案确保类被Spring容器管理Service // 正确添加Service注解 public class UserService { Autowired private UserMapper userMapper; Transactional public void createUser(User user) { userMapper.insert(user); throw new RuntimeException(测试); // 现在事务会正常回滚 } }同时确保组件扫描配置正确Configuration ComponentScan(com.example.service) // 确保包路径正确 public class AppConfig { // ... }体验AI代码助手八、事务管理器配置错误问题现象使用了正确的事务注解但事务不生效或者出现异常。原理分析Spring支持多种事务管理器针对不同的持久化技术DataSourceTransactionManager适用于JDBC和MyBatisJpaTransactionManager适用于JPAHibernateTransactionManager适用于Hibernate如果配置了错误的事务管理器或者在多数据源环境中未指定正确的事务管理器会导致事务失效。解决方案单数据源环境确保配置正确的事务管理器Configuration EnableTransactionManagement public class DatabaseConfig { Bean public DataSource dataSource() { // 数据源配置... return new HikariDataSource(); } Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { // 使用与持久化技术匹配的事务管理器 return new DataSourceTransactionManager(dataSource); } }多数据源环境指定使用的事务管理器Configuration EnableTransactionManagement public class MultiDatabaseConfig { Bean public DataSource primaryDataSource() { // 主数据源配置... return new HikariDataSource(); } Bean public DataSource secondaryDataSource() { // 次数据源配置... return new HikariDataSource(); } Bean public PlatformTransactionManager primaryTransactionManager() { return new DataSourceTransactionManager(primaryDataSource()); } Bean public PlatformTransactionManager secondaryTransactionManager() { return new DataSourceTransactionManager(secondaryDataSource()); } } Service public class UserService { // 指定使用的事务管理器 Transactional(transactionManager primaryTransactionManager) public void createUser(User user) { // 使用主数据源的操作 } Transactional(transactionManager secondaryTransactionManager) public void createUserLog(UserLog log) { // 使用次数据源的操作 } }总结Spring事务是一个强大的特性但也隐藏着许多陷阱。理解这些陷阱的原理可以帮助你更好地利用Spring事务构建更加健壮的应用程序。原文链接https://juejin.cn/post/7507820125946511414

相关文章:

Spring事务失效的8个经典陷阱

Spring事务管理是企业级Java应用的核心功能,看似简单的Transactional注解,如果使用不当将会引发严重的生产问题,比如因事务失效带来的数据不一致问题。事务失效往往不会抛出异常,而是静默发生,等到业务出现问题时才被发…...

LongCat-Image-Editn实用教程:如何用中文指令精准编辑图片

LongCat-Image-Editn实用教程:如何用中文指令精准编辑图片 1. 快速上手:从部署到第一张编辑图 你是不是也遇到过这样的烦恼?拍了一张不错的照片,但总觉得哪里差点意思——背景太乱、颜色不对,或者想给照片里的物品换…...

鼠李糖䇞酶排名

朋友们,最近是不是又在为选酶制剂头疼?看到网上各种“鼠李糖苷酶排名”、“纤维素酶十大品牌”是不是更懵了?今天,咱们不聊虚的,不扯排名,就从一个在生物技术行业摸爬滚打多年的“老炮儿”视角,…...

避坑指南:穿云箭量化平台HP_tdx股票代码转换的6种隐藏陷阱(附正确姿势)

避坑指南:穿云箭量化平台HP_tdx股票代码转换的6种隐藏陷阱(附正确姿势) 在量化交易开发中,股票代码格式转换看似简单,却暗藏诸多玄机。不同行情系统(同花顺、QMT、聚宽)与穿云箭量化平台的HP_td…...

Qwen3-ForcedAligner-0.6B在医疗转录中的应用:精准病历时间戳标注

Qwen3-ForcedAligner-0.6B在医疗转录中的应用:精准病历时间戳标注 1. 引言 医生每天面对大量的问诊录音,要把这些录音转成文字病历已经够麻烦了,更头疼的是还要找出关键症状、诊断意见的具体时间位置。传统方法要么靠人工反复听录音找时间点…...

CST仿真原理:让CST软件告诉你高速差分信号为什么要进行等长匹配

高速差分信号在传输过程中会受到很多因素的影响,如信号衰减、时延不匹配等,这些因素可能会导致信号失真,影响系统性能。为了尽量减小这些影响,需要做等长匹配。 高速差分信号的等长匹配对于电磁干扰(EMI)起…...

市面上的可视挖耳勺怎么样?掏耳神器哪种最好用?耳勺品牌排行榜

​一、引言可视挖耳勺如今热度持续攀升,消费者的购买需求也在稳步增长,但市场上不少产品都存在明显短板 —— 要么图传模糊卡顿,要么操作不稳易划伤耳道,要么续航太短无法满足全家使用。这些问题不仅让掏耳过程变得小心翼翼&#…...

uniapp微信小程序webview嵌套H5页面分享笔记

1、H5端1、index.html引入jweixin.js<script src"https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>2、需要分享的页面postMessageToMiniProgram (shareData) {// alert(JSON.stringify(window.wx))// 1. 判断是否在小程序 web-view 环境中con…...

腾讯混元1.8B翻译模型实测:边缘设备也能跑的专业翻译

腾讯混元1.8B翻译模型实测&#xff1a;边缘设备也能跑的专业翻译 1. 轻量级翻译模型的新选择 1.1 边缘计算时代的翻译需求 在移动互联网和物联网快速发展的今天&#xff0c;我们越来越需要在本地设备上完成高质量的翻译任务。无论是旅行时的实时对话翻译&#xff0c;还是离线…...

Ubuntu24.04兼容性难题:手动部署libwebkit2gtk-4.0与libssl.so.1.1的实战指南

1. 为什么Ubuntu24.04会缺少这两个关键库&#xff1f; 最近在Ubuntu24.04上折腾几个小众软件时&#xff0c;遇到了一个让人头疼的问题&#xff1a;系统提示缺少libwebkit2gtk-4.0和libssl.so.1.1这两个库文件。这让我很困惑&#xff0c;明明是新系统&#xff0c;怎么反而缺少了…...

WHAT - 好用的低代码平台

文章目录一、国际主流低代码平台&#xff08;偏技术/企业级&#xff09;Microsoft Power AppsOutSystemsMendixAppianZoho Creator二、国内低代码平台&#xff08;更接地气&#xff09;钉钉宜搭简道云用友 YonBuilder金蝶云苍穹网易 CodeWave奥哲云枢其他TinyEngine2026 年关键…...

Phi-4-mini-reasoning与.NET生态集成指南

Phi-4-mini-reasoning与.NET生态集成指南 如果你是一名.NET开发者&#xff0c;最近肯定没少听说各种AI大模型。但说实话&#xff0c;很多模型要么太大&#xff0c;本地跑不动&#xff1b;要么效果一般&#xff0c;用起来鸡肋。今天要聊的Phi-4-mini-reasoning&#xff0c;我觉…...

Vue项目实战:Element-UI树形下拉选择器封装全流程(附完整代码)

Vue项目实战&#xff1a;Element-UI树形下拉选择器深度封装指南 在复杂表单场景中&#xff0c;树形下拉选择器是平衡空间利用率和操作效率的经典解决方案。不同于常规平铺式选择器&#xff0c;它通过层级结构组织海量选项&#xff0c;特别适合部门选择、分类导航等具有父子关系…...

Wan2.1视频生成WebUI完整指南:从零开始到精通视频创作

Wan2.1视频生成WebUI完整指南&#xff1a;从零开始到精通视频创作 1. 认识Wan2.1视频生成模型 Wan2.1是阿里巴巴开发的一款强大的视频生成模型&#xff0c;它能够将文字描述转化为生动的视频内容。想象一下&#xff0c;你只需要输入一段文字&#xff0c;就能获得一个完整的视…...

Qwen-Image-Edit与Python集成:自动化图像处理流水线搭建

Qwen-Image-Edit与Python集成&#xff1a;自动化图像处理流水线搭建 1. 引言 电商公司每天需要处理成千上万的商品图片——调整尺寸、更换背景、添加水印、优化画质。传统方式需要设计师一张张手动处理&#xff0c;耗时耗力且成本高昂。现在&#xff0c;通过Qwen-Image-Edit与…...

GLM-OCR在互联网教育中的应用:AI批改手写作业与试卷

GLM-OCR在互联网教育中的应用&#xff1a;AI批改手写作业与试卷 最近和几位做在线教育的朋友聊天&#xff0c;他们都在为一个问题头疼&#xff1a;学生交上来的手写作业和试卷&#xff0c;批改起来太费时间了。老师每天要花好几个小时&#xff0c;盯着屏幕看那些字迹各异的答案…...

ChatGPT免费API实战:如何构建高性价比的智能对话系统

ChatGPT免费API实战&#xff1a;如何构建高性价比的智能对话系统 作为一名开发者&#xff0c;我对ChatGPT这类大语言模型的强大能力感到兴奋&#xff0c;但同时也被其API调用成本所困扰。尤其是在项目初期或预算有限的情况下&#xff0c;如何利用好免费API额度&#xff0c;构建…...

终极Windows网络数据转发:5分钟掌握socat-windows的强大功能

终极Windows网络数据转发&#xff1a;5分钟掌握socat-windows的强大功能 【免费下载链接】socat-windows unofficial windows build of socat http://www.dest-unreach.org/socat/ 项目地址: https://gitcode.com/gh_mirrors/so/socat-windows 你是否曾经在Windows环境下…...

DASD-4B-Thinking实战教程:vLLM模型服务API文档生成+Chainlit集成Swagger

DASD-4B-Thinking实战教程&#xff1a;vLLM模型服务API文档生成Chainlit集成Swagger 1. 引言&#xff1a;为什么需要为模型服务生成API文档&#xff1f; 如果你用过vLLM部署过模型&#xff0c;肯定遇到过这样的场景&#xff1a;模型服务跑起来了&#xff0c;接口也能调通&…...

【狙击主力送战法】操盘五式——【低位启动+空中加油战法】

低位启动就是跟庄家一起建仓布局的时刻&#xff0c;可以随时掌握主力动向以方便后期跟上主力的拉升节奏&#xff0c;俗称‘抄底。’空中加油是短线暴涨中的一种K线图形&#xff0c;在股市里面指的是股价前期有了一定的涨幅&#xff0c;主力需要进行一次市场筹码的换手&#xff…...

网盘直链下载助手:打破限速瓶颈,让文件下载飞起来

网盘直链下载助手&#xff1a;打破限速瓶颈&#xff0c;让文件下载飞起来 【免费下载链接】Online-disk-direct-link-download-assistant 可以获取网盘文件真实下载地址。基于【网盘直链下载助手】修改&#xff08;改自6.1.4版本&#xff09; &#xff0c;自用&#xff0c;去推…...

OPC时代,AI底座先行——FlagOS携Qwen3-8B镜像正式登陆阿里云

OPC 浪潮下&#xff0c;AI 底座成为关键 当前&#xff0c;国内多个省市密集出台 OPC&#xff08;一人公司&#xff09;支持政策&#xff0c;"人 AI 公司"的创业形态正在加速成为现实。OPC 的核心竞争力&#xff0c;不只是选对了哪个大模型&#xff0c;更在于能否搭…...

Claude Code从0到1

1. 环境搭建与基础交互 1.1 安装Claude Code 安装步骤可参考官网或者菜鸟教程 打开Claude Code官网&#xff0c;根据对应操作系统复制相应的下载命令。Windows用powershell&#xff0c;MacOS用bash命令。复制下图中的命令&#xff0c;然后在终端进行粘贴&#xff0c;开始安装…...

Halcon图像处理避坑指南:轮廓转区域时Mode参数的正确选择与常见错误

Halcon图像处理避坑指南&#xff1a;轮廓转区域时Mode参数的正确选择与常见错误 在工业视觉检测项目中&#xff0c;轮廓到区域的转换是图像预处理的关键环节。许多开发者在使用gen_region_contour_xld算子时&#xff0c;往往低估了Mode参数的选择对后续处理的影响。我曾在一个P…...

Visualized-BGE批量推理实战:如何用Python代码将图片编码速度提升3倍

Visualized-BGE批量推理实战&#xff1a;如何用Python代码将图片编码速度提升3倍 在当今多模态AI应用爆炸式增长的时代&#xff0c;高效处理图像嵌入已成为开发者面临的核心挑战之一。Visualized-BGE作为支持中英文的多模态嵌入模型&#xff0c;在跨模态检索任务中表现出色&…...

SRS天线轮发提升信道估计精度

SRS天线轮发技术对上行信道估计准确性的提升机制分析 一、问题解构 用户核心诉求是理解 “SRS天线轮发”如何提升基站对上行信道的估计准确性。该问题需从以下四个维度展开解构&#xff1a; 维度关键子问题说明基础原理SRS是什么&#xff1f;为何能用于信道估计&#xff1f;…...

Z-Image-Turbo_UI界面功能体验:文生图、图生图、图片放大修复全都有

Z-Image-Turbo_UI界面功能体验&#xff1a;文生图、图生图、图片放大修复全都有 作为一名长期从事AI图像生成的技术实践者&#xff0c;我测试过市面上绝大多数开源绘图工具。当第一次接触到Z-Image-Turbo_UI时&#xff0c;最让我惊喜的是它把复杂功能封装在一个简洁的浏览器界…...

基于Halcon的距离变换与分水岭算法在骰子点数识别中的应用

1. 骰子点数识别的技术挑战 在工业检测和游戏自动化领域&#xff0c;骰子点数识别是个典型的机器视觉任务。看似简单的六个小黑点&#xff0c;实际处理时会遇到三大难题&#xff1a;首先是光照条件不稳定&#xff0c;环境光变化会导致骰子表面反光差异&#xff1b;其次是骰子姿…...

通义千问1.5-1.8B-Chat-GPTQ-Int4与MATLAB联动:科学计算问题求解与可视化建议

通义千问1.5-1.8B-Chat-GPTQ-Int4与MATLAB联动&#xff1a;科学计算问题求解与可视化建议 想象一下这个场景&#xff1a;你正在处理一组复杂的实验数据&#xff0c;脑海里已经有了一个清晰的分析思路和可视化方案&#xff0c;但要把这个想法转化成一行行精确的MATLAB代码&…...

django flask+uniapp的个人理财家庭财务收支系统422vl 小程序

目录技术栈选择与分工数据库设计后端实现要点前端UniApp开发开发里程碑计划部署方案性能优化措施测试策略项目技术支持可定制开发之功能创新亮点源码获取详细视频演示 &#xff1a;文章底部获取博主联系方式&#xff01;同行可合作技术栈选择与分工 后端框架采用DjangoFlask组…...