【问题标题】:Don't cover a method in transaction that is running inside a transactional method不要涵盖在事务方法中运行的事务中的方法
【发布时间】:2020-02-20 08:27:48
【问题描述】:

我在某处问过这个问题,

假设我有一个使用 @transactional 在事务中运行的方法 A, 如果有从该事务方法调用的方法 B,默认情况下它也将在同一个事务中运行。

所以,问题是 B 不在交易范围内怎么办, 如何避免B的交易。

【问题讨论】:

  • 方法 A 和 B 属于同一类?或另一个 spring bean 的 B 部分,比如 service.a() 调用 repository.b() ?
  • 是的,在同一个班级。

标签: spring transactions spring-transactions


【解决方案1】:

基于这两个方法都在同一个类中(自调用)的注释,下面的代码可以工作。

 @Service
public class TestService {

    @Autowired // Self autowiring
    TestService service;

    @Transactional
    public void methodA() {
        service.methodB();
    }

    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void methodB() {
        //...
    }
}

service.methodA() 的外部调用将初始化一个事务,而对service.methodB() 的自调用将导致methodB() 也是同一事务的一部分,即使它被注释为不参与事务。 为了解决这个问题,我们会自动装配并在该实例上调用methodB()。这将导致methodB() 的事务配置得到兑现。

以下是自动装配的原因,documentation

在代理模式下(默认),只有外部方法调用 通过代理进来的被拦截。这意味着 自调用(实际上,目标对象中的一个方法调用 目标对象的另一种方法)不会导致实际 即使调用的方法标记为 @Transactional。

参考:Propagation.NOT_SUPPORTED

非事务性执行,如果有则暂停当前事务 存在。类似于 EJB 事务的同名属性。

请仔细阅读共享的文档,了解此传播行为的限制。 希望这会有所帮助

【讨论】:

  • 是的,我想这就是我一直在寻找的东西,如果我只是把这个'@Transactional(propagation = Propagation.NOT_SUPPORTED'放在methodB上没有自动装配会发生什么,
  • 对于 spring txn 管理来检测应用于方法的 txn 行为,对该方法的调用应该通过代理。当我们直接从另一个方法调用该方法时,不涉及代理。为了更好地理解这一点,请通读reference documentation
【解决方案2】:

您必须使用以下模式来获得您想要的:执行 A,如果 B 需要 A 的结果,您可以将其发送到非事务性上下文中。

void myFunction() {
        Object result = myTransactionalClass.A();
        B(result);
}

请注意,既然您在问这个问题(您不希望 B() 是事务性的),那么提到的代码肯定会起作用。

【讨论】:

  • 是的,这可能是一种方式。我认为可能有一些注释之类的东西会阻止你这样做..从那个人问这个问题的方式来看。
猜你喜欢
  • 2014-01-09
  • 2013-05-05
  • 2018-03-09
  • 1970-01-01
  • 2015-09-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-05
  • 2023-03-03
相关资源
最近更新 更多