在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中出现了一些问题和异常,所以我想回滚存储在methodA的saveTableA中的数据,这是同步部分的一部分。 回滚目前没有发生。 请指导我。
您需要像下面这样调整您的代码
服务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);
}
因为您使
methodC
与 methodA
异步执行,所以当 methodC
抛出异常时,methodA
可能已经完成并提交了事务。
如果要依赖
@Transactional
回滚,methodA
必须在methodC
之后完成。所以在这种情况下没有必要让 methodC
异步执行。
如果一定要让
methodC
和methodA
异步执行,没办法只能自己手动回滚。在 methodC
中开始事务以撤消在 methodA
中捕获异常后由 methodC
完成的操作。