[面试题] Spring 事务的传播行为是为了解决什么问题?常见传播属性有哪些?
📖 版块 A:知识讲解版 (温故知新)
-
传播行为要解决的问题:
- 当一个带事务的方法调用另一个也可能带事务的方法时,Spring 需要明确:内层方法到底是加入当前事务,还是新开一个事务,还是必须在已有事务中执行。
- 本质上是在解决事务嵌套和事务边界协调的问题。
-
常见传播属性:
- REQUIRED:如果当前有事务,就加入;如果没有,就新建。最常用。
- REQUIRES_NEW:无论当前有没有事务,都新开一个事务,外层事务会被挂起。
- SUPPORTS:有事务就加入,没有事务就以非事务方式执行。
- MANDATORY:必须在已有事务中执行,否则抛异常。
- NOT_SUPPORTED:不支持事务,如果当前有事务则挂起,以非事务方式执行。
- NEVER:必须在非事务环境执行,如果当前有事务则抛异常。
- NESTED:如果当前有事务,则在当前事务内建立嵌套事务点;没有则类似 REQUIRED。
-
一句话理解:
- 传播行为不是在讲数据库隔离级别,而是在讲“事务方法彼此调用时,事务边界怎么处理”。
🎤 版块 B:面试实战版 (高手逐字稿)
Q:Spring 事务的传播行为是为了解决什么问题?常见传播属性有哪些?
💬 高手逐字稿:
Spring 事务传播行为,核心是为了解决一个非常实际的问题:当一个事务方法去调用另一个事务方法时,内层方法到底应该怎么参与事务。
举个很典型的场景:A 方法上有 @Transactional,A 里面又调用了 B。那 B 到底应该:
- 直接加入 A 的事务?
- 另起一个新事务?
- 强制要求外面必须先有事务?
这些规则,Spring 就统一抽象成了传播行为。
最常见的几个我一般这么记:
第一是 REQUIRED,这是默认值,也是最常用的。意思是:如果当前已经有事务了,那我就加入进去;如果没有,那我自己新开一个。
第二是 REQUIRES_NEW。这个更强势,它不管外面有没有事务,都会自己新开一个事务。外层事务如果存在,会先被挂起,等内层新事务执行完再恢复。
第三是 SUPPORTS,比较温和。有事务我就跟着一起跑,没事务我也能正常执行,只是按非事务方式运行。
第四是 MANDATORY,它比较严格,意思是我必须运行在已有事务里,如果当前没有事务,就直接抛异常。
除此之外还有:
NOT_SUPPORTED:明确不要事务,有就先挂起;NEVER:如果当前存在事务,反而报错;NESTED:如果已经有事务,则在当前事务里建立一个嵌套事务点。
所以这道题最好的总结方式不是背七个单词,而是先把逻辑立住:传播行为关注的不是“事务强不强”,而是“事务方法相互调用时,事务边界怎么协同”。
最后更新于: