使用`@Transactional(propagation = Propagation.NOT_SUPPORTED)`实现事务排除
在Spring框架中,@Transactional
注解是管理事务的常用方式。然而,在某些复杂的业务场景中,我们可能需要对事务进行更精细的控制,例如在父事务中排除某些子事务的参与。本文将探讨如何通过@Transactional(propagation = Propagation.NOT_SUPPORTED)
实现事务排除,并结合实际案例进行详细说明。
一、@Transactional
注解与事务传播行为
@Transactional
注解是Spring中用于声明式事务管理的核心注解。它通过事务传播行为(propagation
)属性来控制事务的执行方式。事务传播行为有以下几种:
REQUIRED
(默认值):如果当前存在事务,则加入该事务;否则创建一个新事务。SUPPORTS
:如果当前存在事务,则加入该事务;否则以非事务方式执行。MANDATORY
:如果当前存在事务,则加入该事务;否则抛出异常。REQUIRES_NEW
:创建一个新事务,如果当前存在事务,则暂停当前事务。NOT_SUPPORTED
:以非事务方式执行,如果当前存在事务,则暂停当前事务。NEVER
:以非事务方式执行,如果当前存在事务,则抛出异常。NESTED
:如果当前存在事务,则在嵌套事务中执行;否则创建一个新事务。
在本文中,我们将重点关注NOT_SUPPORTED
传播行为,它允许我们在某个方法中明确排除事务的参与。
二、实际场景:父事务中排除部分子事务
假设我们有一个父Service,其方法依次调用了四个子Service的方法。父Service的方法被@Transactional
注解标记,因此整个流程默认在一个事务中执行。然而,现在有一个需求:当第四个子Service方法报错时,只回滚第一个和第三个子Service方法的操作,而第二个子Service方法的操作不应被回滚。
三、解决方案:使用@Transactional(propagation = Propagation.NOT_SUPPORTED)
为了实现上述需求,我们可以在第二个子Service方法上使用@Transactional(propagation = Propagation.NOT_SUPPORTED)
注解。这样,当父Service调用该方法时,当前事务将被暂停,该方法将以非事务方式执行,其操作不会受到父事务回滚的影响。
以下是具体的代码实现:
1. 父Service
1 |
|
2. 子Service
1 |
|
3. 测试与结果
假设我们在数据库中进行了一些操作,以下是执行parentMethod
时的预期结果:
- 方法1:参与父事务,如果父事务回滚,其操作将被回滚。
- 方法2:不参与父事务,即使父事务回滚,其操作也不会被回滚。
- 方法3:参与父事务,如果父事务回滚,其操作将被回滚。
- 方法4:参与父事务,如果抛出异常,将导致父事务回滚。
通过@Transactional(propagation = Propagation.NOT_SUPPORTED)
,我们成功地将方法2从父事务中排除,实现了部分事务的独立性。
四、总结
在Spring中,@Transactional(propagation = Propagation.NOT_SUPPORTED)
是一个强大的工具,可以在复杂的业务场景中实现事务的精细控制。通过暂停当前事务并以非事务方式执行特定方法,我们可以确保某些操作不会受到父事务回滚的影响。这种技术在实际开发中非常有用,尤其是在需要部分事务独立性的情况下。
- 本文作者:scwang90
- 本文链接:https://blog.scwang90.cn/2025/04/07/spring-boot-transactional/index.html
- 版权声明:本分享所有文章均采用 BY-NC-SA 许可协议,转载请注明出处!