事务嵌套场景必问:Spring 传播机制如何真正发挥作用?

原文来自于:zha-ge.cn/java/102

事务嵌套场景必问:Spring 传播机制如何真正发挥作用?

说起来,有谁没被Spring的事务传播坑过?春风吹又生的坑------面试一问到"REQUIRES_NEW和NESTED到底哪个'真新建',谁能真正做到子事务独立提交回滚",九成人都变成了表情包: "啊?不是加@Transactional就行了么?"

其实,要不是我去年踩了个"史诗级大雷",我其实也不太敢唧唧歪歪聊这个。下面听我给各位讲个"事务穿越记"。


有一次,产品经理喜提个业务:主流程成功就插日志,日志不插也不能影响主流程。我的第一个反应------这还不简单?日志方法加个@Transactional(propagation = Propagation.REQUIRES_NEW),高高兴兴写代码:

java 复制代码
@Service
public class LogService {
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void logAction(String msg) {
        // 记录日志
        // ...
        // 人为制造异常,验证是否独立
        if (msg.contains("fail")) throw new RuntimeException("日志写入失败");
    }
}

主业务大哥自然地调用 logService.logAction(),想着即使记录日志异常抛了,主流程无所谓。


结果上线一测,这主流程特么居然全回滚了!?脸都绿了。我的先入为主的小算盘------"REQUIRES_NEW自动生成新事务,和外面事务无关",一下给打脸。


踩坑瞬间

真相其实离谱得很,Spring事务传播=面试题,实践全靠玄学踩坑:

  • 内部方法直接调用,事务传播不起效。你以为开了新事务,其实屁都没发生!
  • 没仔细配置事务管理器,REQUIRES_NEW/NESTED压根没新世界可开。
  • 忘了try-catch,异常没吃下来,外层事务直接遭殃。

我的bug现场:

java 复制代码
@Service
public class MainService {
    @Transactional
    public void mainJob(String in) {
        // ...
        logService.logAction("fail log"); // 日志抛异常
        // ...
    }
}

控制台异常一大片,数据库里啥都没,主业务说"锅你背"。 为什么?

  • 自己类里直接调用方法,其实Spring的代理根本没接管到你那层!
  • @Transactional其实只对通过Spring代理调用的新事务管用,self调用和普通调用→全白忙活。

经验启示

这场"看似很会,实际踩坑"的事务体验,直接送我几条血的教训:

  • 切记自调用不走Spring代理,传播属性全靠缘分。不信→看官方文档。
  • REQUIRES_NEW真的要跨service注入调用 才有用,自己调自己=白忙活。
    • 对,比如@Autowired的service,不是this.XX方法。
  • 外部异常记得try-catch,不然后续流程一锅端!
  • NESTED要求底层是支持savepoint的数据库和DataSource,不是所有场景肤浅理解。
  • 面试时如果他追问,就拿"实际开发要看AOP代理切入点、自调用无效、异常catch防止事务传染"这些说出来,气场升天。

再多说一句:"事务传播机制只有你真正把它们玩出事一两次后,才能发自内心懂。"

最后总结下

事务这玩意,看着就几个注解属性,真到生产环境里就是个大型翻车现场。

传播机制的几个关键点,面试和实战都能用得上: REQUIRED:默认选手,外有就加入,没就开新。 REQUIRES_NEW:真·新开事务,但必须通过 Spring 代理调用,异常别忘了 catch。 NESTED:玩 savepoint 的,支持局部回滚,前提是底层数据库和事务管理器撑得住。 SUPPORTS / MANDATORY / NEVER:这仨平时少用,但面试官爱问,知道就好。

一句话总结:传播属性本质上是给"事务边界"立规矩,但要生效得满足两个条件: 1.调用路径必须走 Spring 代理(自调用白搭)。 2.事务管理器和数据库要真支持(不然就是纸上谈兵)。

相关推荐
one year.14 小时前
Linux:线程同步与互斥
java·开发语言
YDS82914 小时前
苍穹外卖 —— Spring Cache和购物车功能开发
java·spring boot·后端·spring·mybatis
苍老流年14 小时前
1. SpringBoot初始化器ApplicationContextInitializer使用与源码分析
java·spring boot·后端
劲墨难解苍生苦14 小时前
spring ai alibaba mcp 开发demo
java·人工智能
leonardee14 小时前
Spring 中的 @ExceptionHandler 注解详解与应用
java·后端
不爱编程的小九九14 小时前
小九源码-springboot103-踏雪阁民宿订购平台
java·开发语言·spring boot
Elieal14 小时前
Spring 框架核心技术全解析
java·spring·sqlserver
组合缺一14 小时前
(对标 Spring)OpenSolon v3.7.0, v3.6.4, v3.5.8, v3.4.8 发布(支持 LTS)
java·后端·spring·web·solon
wheeldown14 小时前
【Linux】Linux 地址空间 + 页表映射的概念解析
java·linux·jvm
源码宝14 小时前
一套随访系统源码,医院随访管理系统源码,三级随访平台源码,技术框架:Java+Spring boot,Vue,Ant-Design+MySQL5
java·源码·软件开发·程序·随访·随访系统源码·三级随访