@Async方法失败时的事务回滚

时间:2019-02-14 05:46:29

标签: java spring asynchronous

我正在尝试阅读有关Transaction的内容,但我什至无法理解如何回退异步方法调用。

我遇到了一个问题,用户可以选择例如手动或无人驾驶汽车。因此,如果他选择无人驾驶,则将禁用手动配置,反之亦然。考虑一下,他正在从无驱动程序变为手动驱动程序,无驱动程序配置已关闭,我打电话给另一个服务以关闭手动配置(这在Async调用中进行)。我添加@Async是有原因的,因为它很耗时。

示例

// Caller
@Override
public void enableDriverlessDriving(DriverlessDriving driverlessConfig) {

     validator.validate(driverlessConfig);

     driverlessDao.update(driverlessConfig);

     if(drivelessConfig.isEnabled()) {

           manualService.onDrivelessEnabled(driverlessConfig.getUserId());
     }
}

// Callee
@Override
@Aysnc
public void onDrivelessEnabled(int userId) {

 .....
   // retrofit rest call. Timeout for 30 secs
   ManualConfig config = client.getManualConfiguration(userid,30);

   config.isEnabled(false);

   try {
         // retrofit rest call. timeout for 30 secs
         client.updateManualConfig(config, userId,30);
   }catch(CheckedExceptions e) { // throwing checked exceptions here.
      LOGGER.error(...)
      return;
   }

}

如果rest调用存在调用错误,以禁用手动配置,则无人驾驶配置已打开,但手动配置未关闭,两者均已打开。

问题:

  1. @Transactional添加到调用方和被调用方方法有效吗? -可能会,但是会影响性能,在这种情况下将不会使用@Async

  2. 调用方方法应该具有@Transactional,但是@Async方法应该具有@Transactional(REQUIRES_NEW)吗?会在调用方方法@Transaction上回滚吗?在被调用方方法中回退已检查异常的事务?

我期望能在不影响性能的情况下实现数据完整性的解决方案(我希望@Async以现在可用的方式工作)

2 个答案:

答案 0 :(得分:1)

这是一个很好的问题,我是在一段时间前遇到的。

  1. 否,添加@Transactional无法正常工作,因为启动@Async方法时,它正在新线程上运行
  2. 我认为无法基于@Async方法调用进行回滚。
  3. 您可以在不进行异步调用的情况下回滚工作,我不知道为什么您需要以@Async的形式调用无人驾驶方法,但是如果将其删除,则可以使用。

答案 1 :(得分:1)

我不建议合并@Async@Transactional,因此我可以以任何一种方式运行该服务。我只是围绕服务创建一个异步包装器,并在需要时使用该包装器。

@与@Async进行交易

@Transactional弹簧@Component调用带有@Async注释的方法时,不会发生这种情况。异步方法的调用将在以后由任务执行程序安排和执行,因此被视为“新”调用,即没有事务上下文。如果@Async方法(或声明它的@Component)本身不是@Transactional,Spring将不会管理任何需要的事务。

如果使用@Async批注,则应特别注意事务。在这种情况下,事务将通过调用层次结构从一个Spring @Component传播到另一个。

为了使Spring管理@Async方法的交易,@Component或方法本身应声明@Transactional批注,这样Spring将管理事务,即使方法是异步执行的。