英文:
Spring Boot Async Transaction Rollback Issue
问题
在methodC
中出现了问题并引发了异常,因此我想要回滚存储在methodA
的saveTableA
中的数据,这是同步部分的一部分。目前回滚没有发生。请指导我。
英文:
Facing 1 strange issue in spring boot @Async and @Transactional, following is sample code:
ServiceA
@Transactional
public ResponseA methodA() {
try {
// some code
saveTableA() //save some data to tableA
serviceB.methodB();
} catch(Exception e) {
e.printStacktrace();
}
return response;
}
ServiceB
@Async
public void methodB() {
try {
// some code
serviceC.methodC();
save some data to tableB
} catch(Exception e) {
e.printStacktrace();
throw new ServiceException(ex.getMessage());
}
}
ServiceC
public void methodC() throws Exception {
try {
// some code
call to another service // this is failing sometime
} catch(Exception e) {
e.printStacktrace();
throw e;
}
}
now in methodC there is some issue and exception occur, so I want to rollback data stored in methodA's saveTableA, which is part of synchronous part.
Rollback is currently not happening.
Please guide me.
答案1
得分: 1
因为您使methodC
与methodA
异步执行,当methodC
抛出异常时,methodA
可能已经完成并提交了事务。
如果您希望依赖@Transactional
来回滚,那么methodA
必须在methodC
之后完成。如果是这种情况,那么让methodC
异步执行就没有意义。
如果您必须使methodC
与methodA
异步执行,那么您只能选择手动回滚。在methodC
中启动一个事务,在methodC
捕获异常后撤销methodA
所做的操作。
英文:
Because you make methodC
executes asynchronously with methodA
, it is possible that when methodC
throws exception , methodA
already completed and committed the transaction.
If you want to relies on @Transactional
to rollback, methodA
have to complete after methodC
. So there is no points to make methodC
executes asynchronously if this is the case.
If you must make methodC
to execute asynchronously with methodA
, you have no choices but only can manually rollback by yourself . Start a transaction in methodC
to undo what are done by methodA
after you catch exception in methodC
.
答案2
得分: 0
ServiceA:
@Transactional
public ResponseA methodA() {
try {
// 一些代码
saveTableA() // 将一些数据保存到表A
serviceB.methodB();
} catch(Exception e) {
throw new RuntimeException(e);
}
return response;
}
ServiceB:
@Async
public Future<?> methodB() {
try {
// 一些代码
serviceC.methodC();
// 将一些数据保存到表B
} catch(Exception e) {
return AsyncResult.forExecutionException(e);
}
return new AsyncResult<>(null);
}
英文:
You need to adjust your code like below
ServiceA:
@Transactional
public ResponseA methodA() {
try {
// some code
saveTableA() //save some data to tableA
serviceB.methodB();
} catch(Exception e) {
throw new RuntimeException(e);
}
return response;
}
ServiceB:
@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);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论