Spring中@Async方法上的@Transactional

8

我有一个场景,在这个场景中,我调用了三个@Transactional @Async方法。除了所有三个方法都有自己的事务上下文之外,一切都运行良好。我希望在调用方法的事务上下文中执行它们。

我的调用方法如下:

 @Transactional
 public void execute(BillingRequestDto requestDto) {
        try {
            LOGGER.info("Start Processing Request : {}", requestDto.getId());
            List<Future<?>> futures = new ArrayList<>();
            futures.add(inboundProcessingService.execute(requestDto));
            futures.add(orderProcessingService.execute(requestDto));
            futures.add(waybillProcessingService.execute(requestDto));
            futures.stream().parallel().forEach(future -> {
                try {
                    future.get();
                } catch (Exception e) {
                    futures.forEach(future1 -> future1.cancel(true));
                    throw new FBMException(e);
                }
            });
            requestDto.setStatus(RequestStatus.SUCCESS.name());
            requestDto.setCompletedAt(new Date());   
            LOGGER.info("Done Processing Request : {}", requestDto.getId());

        } catch (Exception e) {
            requestDto.setStatus(RequestStatus.FAIL.name());
            requestDto.setCompletedAt(new Date());
            throw new FBMException(e);
        } 
    }

所有调用的方法都使用@Async@Transactional注解。

@Transactional
@Async
public Future<Void> execute(BillingRequestDto requestDto) {
    LOGGER.info("Start Waybill Processing {}", requestDto.getId());
    long count = waybillRepository.deleteByClientNameAndMonth(requestDto.getClientName(), requestDto.getMonth());
    LOGGER.info("Deleted  {} Records for Request {} ", count, requestDto.getId());
    try (InputStream inputStream = loadCsvAsInputStream(requestDto)) {
        startBilling(requestDto, inputStream);
    } catch (IOException e) {
        LOGGER.error("Error while processing");
        throw new FBMException(e);
    }
    LOGGER.info("Done Waybill Processing {}", requestDto.getId());
    return null;
}

所有三种方法的实现基本上是相同的。

现在,如果任何一种方法出现故障,则该方法的事务将被回滚。

我的要求是在调用方法的事务上下文中运行所有三个方法,因此一个方法中的任何异常都将回滚所有三个方法。

如果我禁用@Async,则此场景运作良好。由于有耗时的方法,因此我希望它们可以并行运行。

请为此提供任何解决方案。


3
@Async 方法在单独的线程中执行,因此不能使用调用者的相同事务。 - Chacko
2个回答

3
我猜你应该使用Spring TransactionTemplate进行编程控制。
主线程应该执行控制,如果任何线程抛出异常,您应该通知其他线程它们应该回滚。
例如,每个“事务性”线程在执行后应该wait(),如果没有异常,只需执行notifyAll()并在您的线程中执行事务提交,在发生异常的情况下,您应该调用Thread.interrupt()并执行回滚。

0

我认为你的@Async方法可能会抛出已检查异常

@Transactional
@Async
public Future<Void> execute(BillingRequestDto requestDto) throw RollBackParentTransactionException {
...
}

同时,调用者也可以被注解为:

@Transactional(rollbackFor = RollBackParentTransactionException.class)
public void execute(BillingRequestDto requestDto) { ... }

那应该可以工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接