Spring Boot 异步事务回滚问题

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

在spring boot @Async 和@Transactional 中遇到1个奇怪的问题,下面是示例代码:

服务A

@Transactional
public ResponseA methodA() {
    try {
        // some code
        saveTableA() //save some data to tableA
        serviceB.methodB();
    } catch(Exception e) {
        e.printStacktrace();
    }
    return response;
}

服务B

@Async
public void methodB() {
    try {
        // some code
        serviceC.methodC();
        save some data to tableB
    } catch(Exception e) {
        e.printStacktrace();
        throw new ServiceException(ex.getMessage());
    }
}

服务C

public void methodC() throws Exception {
    try {
        // some code
        call to another service // this is failing sometime
    } catch(Exception e) {
        e.printStacktrace();
        throw e;
    }
}

现在在methodC中出现了一些问题和异常,所以我想回滚存储在methodAsaveTableA中的数据,这是同步部分的一部分。 回滚目前没有发生。 请指导我。

spring-boot asynchronous spring-data-jpa transactions rollback
2个回答
0
投票

您需要像下面这样调整您的代码

服务A:

@Transactional
public ResponseA methodA() {
    try {
        // some code
        saveTableA() //save some data to tableA
        serviceB.methodB();
    } catch(Exception e) {
        throw new RuntimeException(e);
    }
    return response;
}

服务B:

@Async
public Future<?> methodB() {
    try {
        // some code
        serviceC.methodC();
        save some data to tableB
    } catch(Exception e) {
       return AsyncResult.forExecutionException(e);
    }
    return new AsyncResult<>(null);
}

0
投票

因为您使

methodC
methodA
异步执行,所以当
methodC
抛出异常时,
methodA
可能已经完成并提交了事务。

如果要依赖

@Transactional
回滚,
methodA
必须在
methodC
之后完成。所以在这种情况下没有必要让
methodC
异步执行。

如果一定要让

methodC
methodA
异步执行,没办法只能自己手动回滚。在
methodC
中开始事务以撤消在
methodA
中捕获异常后由
methodC
完成的操作。

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