我正在尝试阅读有关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调用存在调用错误,以禁用手动配置,则无人驾驶配置已打开,但手动配置未关闭,两者均已打开。
问题:
将@Transactional
添加到调用方和被调用方方法有效吗? -可能会,但是会影响性能,在这种情况下将不会使用@Async
。
调用方方法应该具有@Transactional
,但是@Async
方法应该具有@Transactional(REQUIRES_NEW)
吗?会在调用方方法@Transaction
上回滚吗?在被调用方方法中回退已检查异常的事务?
我期望能在不影响性能的情况下实现数据完整性的解决方案(我希望@Async
以现在可用的方式工作)
答案 0 :(得分:1)
这是一个很好的问题,我是在一段时间前遇到的。
@Transactional
无法正常工作,因为启动@Async
方法时,它正在新线程上运行@Async
方法调用进行回滚。@Async
的形式调用无人驾驶方法,但是如果将其删除,则可以使用。答案 1 :(得分:1)
我不建议合并@Async
和@Transactional
,因此我可以以任何一种方式运行该服务。我只是围绕服务创建一个异步包装器,并在需要时使用该包装器。
@与@Async进行交易
当@Transactional
弹簧@Component
调用带有@Async
注释的方法时,不会发生这种情况。异步方法的调用将在以后由任务执行程序安排和执行,因此被视为“新”调用,即没有事务上下文。如果@Async
方法(或声明它的@Component
)本身不是@Transactional
,Spring将不会管理任何需要的事务。
如果使用@Async
批注,则应特别注意事务。在这种情况下,事务将通过调用层次结构从一个Spring @Component
传播到另一个。
为了使Spring管理@Async
方法的交易,@Component
或方法本身应声明@Transactional
批注,这样Spring
将管理事务,即使方法是异步执行的。