@Transactional事务问题

简介: 本文详解Spring事务三大失效场景:①try-catch吞异常未抛出;②Checked异常未配置`rollbackFor`;③同类自调用绕过代理。附正确解决方案与生产实践建议,助你避开事务坑!(238字)

前言

Spring事务默认只对 RuntimeException 和 Error 回滚,对 Checked Exception 不回滚;如果方法抛出 Checked Exception 且未配置 rollbackFor,事务会被正常提交。
Spring事务只在“代理对象调用方法时”生效,类内部 self-invocation(自调用)会绕过代理。


一、try/catch 里把异常“吃掉了,事务不会回滚

例子:

@Transactional
    @GetMapping("/test1")
    public void create() {
   
        try {
   
            orderMapper.insert(new order(1L,1L));
            // 模拟异常
            int a = 1 / 0;
        } catch (Exception e) {
   
            System.out.println("异常被捕获了:" + e.getMessage());
        }
    }

解决:
1.直接不 catch

@Transactional
public void create() {
   
     orderMapper.insert(new order(1L,1L));
    int a = 1 / 0; // 自动回滚
}

2.重新抛出异常

@Transactional
public void create() {
   
    try {
   
        orderMapper.insert(new order(1L,1L));
        int a = 1 / 0;
    } catch (Exception e) {
   
        System.out.println("记录日志");
        throw new RuntimeException(e); // ⭐关键:必须抛出去
    }
}

3.手动标记回滚

@Transactional
public void create() {
   
    try {
   
        orderMapper.insert(new order(1L,1L));
        int a = 1 / 0;
    } catch (Exception e) {
   
        TransactionAspectSupport.currentTransactionStatus()
                .setRollbackOnly();
    }
}

二、方法抛出 Checked Exception 且未配置 rollbackFor,事务不会回滚

例子:

@Transactional
public void test() throws Exception {
   
    throw new Exception("编译时异常");
}

❗关键原因

Spring 的逻辑是:

“我只会对 RuntimeException 感兴趣”

你的 Exception 是:

Checked Exception → Spring 默认忽略回滚

解决:
方案1:强制所有异常都回滚(推荐)

@Transactional(rollbackFor = Exception.class)
public void test() throws Exception {
   
    throw new Exception("库存不足");
}

方案2:统一用 RuntimeException

@Transactional
public void test() {
   

    throw new RuntimeException("库存不足");
}

三:@Transactional 在同类方法调用会失效

例子:

@Service
public class OrderService {
   

    public void createOrder() {
   

        insertOrder(); // ❌ 同类调用
    }

    @Transactional
    public void insertOrder() {
   

        orderMapper.insert(...);

        int a = 1 / 0; // 期待回滚
    }
}

实际发生什么?

createOrder() → 直接调用 insertOrder()

❌ 没经过 Spring 代理
❌ @Transactional 不生效

Spring事务基于AOP代理实现,仅在通过代理对象调用方法时生效;同类内部方法调用属于 self-invocation,不会经过代理,因此事务不会生效。

正确解决方案(重点)
✔ 方案1:拆服务(最推荐)

@Service
public class OrderService {
   

    @Autowired
    private OrderTxService orderTxService;

    public void createOrder() {
   
        orderTxService.insertOrder();
    }
}
@Service
public class OrderTxService {
   

    @Transactional
    public void insertOrder() {
   
        orderMapper.insert(...);
    }
}

方案2:通过代理调用自己(不推荐但可用)

@Autowired
private ApplicationContext context;

public void createOrder() {
   

    OrderService proxy = context.getBean(OrderService.class);

    proxy.insertOrder(); // ✔ 走代理
}

四:private 方法导致事务失效

@Transactional
private void b() {
   }

❗原因

Spring AOP 无法代理 private 方法
只能代理 public/protected

总结

Spring 的声明式事务基于 AOP 实现。@Transactional 只是事务声明,Spring 会通过 JDK 动态代理或 CGLIB 为目标 Bean 创建代理对象。方法调用时先进入事务拦截器,由事务拦截器负责开启事务、提交事务和回滚事务。因此事务能否生效的关键在于是否经过代理对象,这也是同类调用、private 方法、final 方法等场景事务失效的根本原因。

面试生产环境中事务怎么使用?

1.统一配置 rollbackFor = Exception.class
2.非核心业务拆解,用异步保证一致性
3.统一异常体系:继承RuntimeException重写异常类
4.事前压测

@作者:加辣椒了吗?
简介:憨批大学生一枚,喜欢在博客上记录自己的学习心得,也希望能够帮助到你们!

相关文章
|
7天前
|
人工智能 安全 测试技术
AI 驱动的自主开发平台 Qoder CN 实战:融合专家多智能体、安全沙箱、Hook 扩展及 CLI 命令与应用案例
Qoder CN依托Quest2.0任务引擎、专家团多智能体协同、Repowiki工程知识库、终端沙箱安全隔离、Hook扩展机制,完成从简单代码补全向工程级自主开发工作台的跨越。提供原生IDE、主流IDE插件、CLI命令行多形态接入,兼容多款主流大模型,兼顾个人开发者与企业团队的研发场景。 在实际项目落地,优先使用Quest做中等规模工程任务,搭配Repowiki沉淀项目知识;开启沙箱保障终端执行安全;根据任务复杂度切换不同基座模型,做好Credits资源告警;AI产出代码坚持人工复核。借助整套工具链,可以把大量重复编码、
162 2
|
15天前
|
弹性计算 小程序 测试技术
阿里云轻量应用服务器多少钱一年?2026年付月付价格全解析
综合来看,2026年阿里云轻量应用服务器租用价格覆盖从24元/月到234元/月的月付区间,以及38元/年到1599元/年的年付档位,核心优势在于200M峰值带宽与不限流量的套餐模式,以及低至38元/年的入门门槛。个人开发者或学生优先选择2核2G的38元秒杀款或68元常规款,低成本满足学习、测试与个人项目需求;中小企业可根据业务负载选择2核4G的379元或4核8G的1159元配置,兼顾性能与成本;跨境业务用户直接选择海外或香港地域的月付套餐,24元起即可免备案部署。建议在采购前先通过CLI或官网价格计算器核算不同付费周期下的总成本,结合业务负载与运行周期选择最契合的配置与计费方式,避免无效支出,
277 2
|
17天前
|
存储 自然语言处理 NoSQL
GraphRAG详解:基于图检索增强生成,打通大模型关联推理,落地复杂知识图谱问答25.6
GraphRAG是融合知识图谱与大模型的进阶RAG技术,通过实体关系抽取构建图谱,结合图结构检索与向量召回,解决传统RAG在多跳推理、因果关联、事实溯源上的短板,提升复杂问题回答的准确性与可解释性。
163 3
|
1月前
|
人工智能 自然语言处理
AI模型上下文长度是什么意思?AI 大模型 128k/256k/1M 到底有多强?一文讲透
上下文长度指大模型单次能处理的最大Token数(含输入+输出),决定其记忆与理解长文本能力。128K≈16万汉字,1M可达百万级,支持书籍、代码库等超长内容处理。在阿里云百炼官网:https://t.aliyun.com/U/fPVHqY 免费领取千万Tokens
294 3
|
1月前
|
算法 数据挖掘 Shell
经验自进化:自动挖掘经验资产,消融实验验证真实收益丨AgentLoop 数据飞轮实践(五)
本文介绍AgentLoop经验自进化实践:从运行轨迹自动挖掘成功与失败模式,经Skill召回并注入上下文。文章详解接入验证流程,并通过消融实验优化召回策略,降低耗时、成本、Token消耗和工具调用,让Agent持续迭代。
410 15
|
1月前
|
BI API 语音技术
阿里云百炼平台新人免费额度完整实操指南:领取规则、额度查看、用完即停与API代码调用全解
对于初次接触大模型开发、原型验证、智能应用搭建的个人开发者与企业技术团队来说,平台新人免费额度是降低试错成本的重要资源。开发者可以借助免费额度完成模型能力验证、应用原型调试、业务场景POC测试,不用一开始就投入按量付费成本。百炼大模型服务平台提供面向新开通用户的新人免费推理额度,但这套权益附带地域限制、有效期、额度隔离、账号共享、扣费防护等一系列复杂规则,如果对规则理解不到位,容易出现额度看不到、提前过期、子账号消耗完主账号额度、免费阶段产生意料之外账单等问题。本文完整梳理新人免费额度全部规则,讲解额度获取、多途径查看剩余额度、用完即停防护功能,附带可直接运行curl、Python调用代码,梳
465 1
|
1月前
|
缓存 Shell Linux
dsh 更新了版本没变怎么办?DeepSeek Harness 多份安装、PATH 与缓存排查
dsh 更新了版本没变,先分清三层:磁盘上的包、PATH 命中的命令、正在跑的进程。最常见是服务没重启与多份安装;本文给 which -a、npm root -g、hash -r 与缓存、镜像滞后的逐项排查。
344 3
|
1月前
|
前端开发 IDE Android开发
Qoder 上新 Mobile Use,开始验证移动端应用
Computer Use 已经可以操作电脑,Browser Use 可以进入正在使用的浏览器。Qoder 推出 Mobile Use 插件(Beta),在安卓、鸿蒙与 iOS 上将代码修改接入真机或模拟器,完成运行、交互与结果确认。
392 1
|
26天前
|
人工智能 运维 IDE
Qoder CN 深度解读|原通义灵码升级,AI 研发智能体矩阵、版本对比及多端落地指南
完成品牌升级的Qoder CN(原通义灵码)跳出传统代码插件定位,进化为覆盖编码、办公、终端、企业云端管控的全栈AI智能体产品矩阵。通过个人免费社区版、个人专业版、企业标准版、VPC私有化四大分层版本,完整覆盖零基础学习、单人商业开发、大型合规企业等不同人群的需求。
280 0
|
1月前
|
人工智能 API 调度
阿里云百炼大模型服务器平台深度解析:一站式AI模型训推、部署与API实操全教程
随着大模型技术大规模落地,不管是个人开发者做原型验证,还是企业搭建行业AI应用,都绕不开模型算力调度、推理服务部署、模型微调优化、应用集成等一系列难题。如果自行搭建整套大模型运行环境,需要采购高性能GPU算力,完成底层框架部署、网络调优、容灾维护,不仅硬件投入成本高昂,运维门槛同样很高,普通开发团队很难独立完成整套体系搭建。阿里云百炼作为一站式大模型服务器平台,整合了模型托管、算力调度、微调训练、推理部署、智能体编排、知识库检索增强等全套能力,把底层复杂的算力服务器集群做封装,开发者无需关心GPU硬件运维,只需要聚焦上层业务逻辑,就可以完成从模型调用、定制调优到业务系统上线的完整流程。本文将从
547 1

热门文章

最新文章