理解嵌套方法调用中的@Transactional 行为

问题描述 投票:0回答:1

我有一个用

@Transactional
注释的方法,在这个方法中,我调用另一个没有用
@Transactional
注释的方法。我正在尝试理解这种情况下的事务行为。

我的问题是:

  1. 当调用
    methodA()
    时,
    methodB()
    是否在由
    methodA()
    发起的同一事务内执行?
  2. 如果
    methodB()
    发生异常,会导致
    methodA()
    中的事务回滚吗?

这里有一个例子来说明:

@Service
public class MyService {

    @Transactional
    public void methodA() {
        // some database operations
        methodB();
    }

    public void methodB() {
        // some other database operations
    }
}
java spring spring-boot transactions spring-transactions
1个回答
0
投票

在 Spring 中处理事务行为时,了解如何跨方法调用管理事务非常重要。以下是根据您的情况进行的详细说明:

  1. 交易传播 当调用 methodA() 时,methodB() 是否在 methodA() 发起的同一事务中执行?

是的,methodB() 在由 methodA() 启动的同一事务中执行。在Spring中,如果一个方法被@Transactional注解,则该事务由代理管理。当 methodA() 被调用时,代理启动一个事务。由于 methodB() 是从 methodA() 内部调用的,因此它在同一事务的上下文中执行。 methodA() 上的 @Transactional 注释确保整个执行上下文(包括对同一类中其他方法的调用)在同一事务中运行。 2. 异常处理和事务回滚 如果methodB()中发生异常,是否会导致methodA()中的事务回滚?

是的,如果methodB()中发生异常,并且没有在methodB()内捕获和处理,它将传播到methodA(),导致事务回滚。默认情况下,Spring 将针对任何未经检查的异常(RuntimeException 的子类)或错误回滚事务。检查的异常(Exception 的子类,不包括 RuntimeException)不会触发回滚,除非明确配置为这样做。

以下是该行为的摘要:

Unchecked Exception (RuntimeException or its subclass): The transaction will be rolled back.
Checked Exception (Exception but not RuntimeException): The transaction will not be rolled back unless specified.

异常处理示例

以下是异常处理的示例:

java

@服务 公共类 MyService {

@Transactional
public void methodA() {
    try {
        // some database operations
        methodB();
    } catch (Exception e) {
        // Handle exception if needed
        // Optionally rethrow the exception to trigger rollback
        throw e; // This will cause the transaction to roll back
    }
}

public void methodB() {
    // some other database operations
    if (someCondition) {
        throw new RuntimeException("An error occurred"); // This will trigger rollback
    }
}

}

在此示例中:

If someCondition in methodB() is true, methodB() will throw a RuntimeException.
Since RuntimeException is an unchecked exception, it will propagate up to methodA().
The transaction managed by methodA() will be marked for rollback due to the uncaught RuntimeException.

重要注意事项

Transaction Management: Ensure your Spring configuration is correctly set up to enable transaction management, usually with @EnableTransactionManagement in a configuration class.
Proxy Limitation: Transactional behavior is managed by proxies in Spring. Direct internal calls (i.e., one method in the same class calling another method without going through the proxy) will not go through the transactional proxy. This is not an issue in your example as methodA() calls methodB() internally within the same transaction.

总之,在您的示例中,methodB() 在由 methodA() 启动的同一事务中运行。如果 methodB() 中发生异常并传播到 methodA(),它将导致事务回滚,前提是该异常是未经检查的异常。

© www.soinside.com 2019 - 2024. All rights reserved.