全网最通俗!Spring 事务传播行为用故事讲明白了!

B站影视 内地电影 2025-06-06 10:07 1

摘要:嗨大家好呀,我是小米,一个31岁的Java开发工程师,今天依然在南京热辣滚烫的代码世界中努力生存,最近在准备一次社招面试,面到一题经典的不能再经典的老朋友:

嗨大家好呀,我是小米,一个31岁的Java开发工程师,今天依然在南京热辣滚烫的代码世界中努力生存,最近在准备一次社招面试,面到一题经典的不能再经典的老朋友:

“你说一下Spring的事务传播行为?”

我当场一愣:这不是我平时用得很顺手的@Transactional吗?怎么突然要我掏出原理了!

但你知道的,程序员嘛,手一抖就想深挖——于是乎,小米又熬了一晚,看完官方文档、源码、博客、项目代码……干脆整理出来这篇文章,咱不但要能回答,还得能讲出花儿来!

首先,要明确一件事:

这个问题不是在问你“记住了几个枚举常量”,而是在问你:

你知道这些传播行为怎么运作吗?

在实际项目中你用过哪些,遇到过什么坑,怎么解决的?

好啦,先正经解释一下:

在Spring中,事务传播行为(Propagation)定义了一个有事务的方法调用另一个有事务的方法时,应该如何处理事务上下文。

也就是说:

假如你现在在方法A里用了@Transactional,然后它调用了方法B,方法B也用了@Transactional,那——请问B要用A的事务吗?还是重新开一个新的?

这就是传播行为来决定的。

我们一个个来过——不靠死记硬背,而是讲“情景故事”,让你面试、写代码、debug都能瞬间反应。

1. PROPAGATION_REQUIRED(需要当前事务)

解释

如果当前存在事务,就加入该事务;如果没有事务,就新建一个事务。

小米的故事

就像你在吃火锅,突然你朋友来了。他说:“你已经点单了,那我就坐你这桌,咱们一起吃。”——省事儿省钱。

应用场景

这是默认值,也是最常用的。一个方法调用另一个方法,大家共享一个事务,这样在操作数据库时统一提交或回滚。

坑点提示

事务失效的大部分锅就出在这里!例如:

结论:自调用会绕过代理,事务不会生效。

2. PROPAGATION_REQUIRES_NEW(新建一个事务)

解释

总是新建一个事务。如果外面已经有事务了,就挂起外部事务。

小米的故事

你跟朋友吃火锅,他还在点菜,这时候你说“我还有点事,我自己开张新桌先吃了!”等他点完再来找你。

应用场景

A方法要执行B,但B无论成功失败都不能影响A。日志保存场景(即便主事务失败,日志也要记住)。

示例代码

3. PROPAGATION_NESTED(嵌套事务)

解释

如果当前有事务,就在这个事务中创建一个“嵌套点”(savepoint);否则新建事务。

小米的故事

你跟朋友合开一桌火锅,但你怕他点太多,于是你记录了自己点的那些菜。如果等会你觉得吃太撑了,可以退掉你点的,朋友的保留。

应用场景

适合部分回滚的业务。

注意

需要数据库支持“保存点机制”(如MySQL的InnoDB)。不同于REQUIRES_NEW,它不挂起外部事务,而是在当前事务中设置回滚点。

4. PROPAGATION_SUPPORTS(支持当前事务)

解释

有事务就用,没有就非事务地运行。

小米的故事

朋友在吃火锅你加入,你就跟着吃;朋友不吃,你也不点菜,喝点水看看剧。

应用场景

读操作为主,灵活点即可。

5. PROPAGATION_NOT_SUPPORTED(不支持事务)

解释

当前有事务就挂起它,自己无事务地运行。

小米的故事

“火锅我不吃了,我减肥呢。我在旁边点个水果拼盘,不跟你们掺和。”

应用场景

一些不需要事务的代码,比如操作Redis、记录日志、调用远程服务等。

6. PROPAGATION_NEVER(绝对不能有事务)

解释

如果当前有事务,直接抛异常。

小米的故事

“你这桌有火锅?那我不去了,油烟太重我过敏!”

应用场景

真的极少用,除非你确定某段逻辑不能被事务管理(比如某些审计操作)。

7. PROPAGATION_MANDATORY(必须要有事务)

解释

如果当前没有事务,就抛异常。

小米的故事

“火锅必须组团才能吃,我一个人不点。”

应用场景

比如你设计了一段核心业务,必须放在事务中执行,不然就炸!

背景:某服务A里调用B和C两个方法,都带有@Transactional,希望C失败了也不要影响A。

我脑子一拍,用了REQUIRES_NEW,C确实不影响A了。但新问题出现了:

B的方法是REQUIRED,它执行失败抛异常后,A事务回滚了,但C提交了!

等于C的数据和其他都不一致了!!

解决方案:

我加了异常处理和业务补偿,让C的事务与A“解耦”,但在逻辑层上又用“事件通知”方式做回滚补偿。

这个事让我意识到一个关键点:

传播行为不是事务边界的终点,而是事务策略的一部分。真正安全的业务逻辑,必须结合异常处理、日志、幂等、补偿等机制。

能讲出行为的意图和场景能在项目中做出正确选择能预判可能产生的问题(比如挂起事务、异常传播、事务失效)

最后,送大家一段小米总结口诀:

必须有就MANDATORY,有也不行是NEVER;不管有没有就SUPPORTS,没有别跑是REQUIRED;挂起重开REQUIRES_NEW,嵌套事务NESTED修;不管事务我不管,NOT_SUPPORTED有你秀。

这年头,光能写CRUD已经不够了,理解事务传播这种“细节上的大问题”,才是真正的Java高手之路。

如果你觉得这篇文章有帮助,欢迎【点赞+转发+在看】,也欢迎留言聊聊你在用事务传播时遇到的坑!

来源:雅雯教育分享

相关推荐