是否可以在 Spring 中从非事务方法调用事务方法?

Posted

技术标签:

【中文标题】是否可以在 Spring 中从非事务方法调用事务方法?【英文标题】:Is it possible to invoke transactional method from non transactional method in Spring? 【发布时间】:2015-09-01 08:17:16 【问题描述】:

假设我有一个 Repository 类。

@Repository
class MyRepository 

    @Transactional
    void method1 () 
        // some logic here
    

    void method2 () 
        // some logic here
        method1();
        // some logic here
    

是否可以在字符串中做到这一点?它是如何工作的?

【问题讨论】:

该特定示例是自调用,不适用于通常的代理 AOP。 我怎样才能让它发挥作用? 通常控制器是一个调用层服务的非事务类,内部有事务方法是一个好习惯。我看不出有什么问题,如果你的问题需要这种行为,你可以毫无问题地做到这一点。 但是由于@chrylis 描述的原因,我的代码无法正常工作。我相信有一些技巧可以使它与非标准代理机制一起工作。 我认为有一种方法可以通过将@Autowired private ApplicationContext context; 添加到您的存储库中,然后当您从method2 调用method1 时,您可以这样做((MyRepository)context.getBean(getClass())).method1()。不过我建议不要这样做。 【参考方案1】:

这不起作用,因为这是一个自调用。见Spring @Transaction method call by the method within the same class, does not work?

根据您的应用程序及其职责,您可以为method2() 创建另一个bean。 除此之外,DAO 方法通常不应注解@Transactional。见Where does the @Transactional annotation belong?

【讨论】:

可以使用 org.springframework.aop.framework.AopContext 使其工作......但建议不要使用它。【参考方案2】:

这不起作用,因为当您调用method2 时,该方法将超出@Transaction 的范围。但是您可以通过以下方式应用 hack 并使用 thismethod1 调用 method2

this.method2();

【讨论】:

【参考方案3】:

您应该使用自注入从非 Transactional 调用 Transactional 方法,就像在 Spring 中一样,由于 AOP 代理的事情,您不能简单地从同一实例调用 @Transactional 方法

@Repository
class MyRepository 

    @Autowired
    MyRepository selfTxMyRepository;

    @Transactional
    void method1 () 
        // some logic here
    

    void method2 () 
        // some logic here
        selfTxMyRepository.method1();
        // some logic here
    

在这里查看一些解释:https://vladmihalcea.com/the-open-session-in-view-anti-pattern/

【讨论】:

【参考方案4】:

您不能这样做,因为 Spring 包装了将从另一个类(服务)调用的方法。如果您从同一个类中调用带注释的方法,Spring 将什么也不做,因为它无法包装它们。

【讨论】:

以上是关于是否可以在 Spring 中从非事务方法调用事务方法?的主要内容,如果未能解决你的问题,请参考以下文章

Spring中同一个service中方法相互调用事务不生效问题解决方案

Spring事务的传播

Spring事务传播机制

Spring事务传播机制详解

Spring事务传播机制详解

每日问答,Spring事务