Spring对异步事务方法的catch错误进行操作



我已经阅读了Spring@Transactional-isolation,propagation 中的指令

但我不明白我解释的这个特性是如何产生的:我有一个像这样的异步方法

@Transactional(timeout = TRANSACTION_TIMEOUT, propagation = Propagation.REQUIRES_NEW)
@Async("asyncImportExecutor")
public void startBeggin(Long id, String jwtToken) {
try {
. . .
} catch (Exception e) {
log.error("Error: " + e);
utilsService.setFlag(id, 0L); // every type of error, revert flag to 0
}

在catch上调用的utilService方法,是这个吗

public void setFlag(Long id, Long state) {
/* recover data from repository */
Processo processo = getRepo().getOne(id);
processo.setAvanzamento(state);
getRepo().saveAndFlush(processo);
}

该方法(setFlag(在调用异步方法之前经过1L调用一次

getService().setFlag(id, (long) 1);

并且在异步方法中的所有操作结束时通过零

getService().setFlag(id, (long) 0);

但是,如果异步方法由于某些问题而失败,catch分支中的调用就会失败,因为

org.springframework.orm.jpa.JpaSystemException: Transaction was marked for rollback only; cannot commit; nested exception is org.hibernate.TransactionException: Transaction was marked for rollback only; cannot commit

并且标志保持为1。

所以,我希望我是清楚的,但是。。。在回滚异步方法(startBeggin(中的操作之后,在这些操作之间发生任何异常时,我如何确保在该对象上设置该值?

如何在对象上、事务(失败(的roolback上设置(或更新(字段?

受事务方法影响的对象是相同的(通过ID恢复(,但所有roolbacked操作都没有链接到该标志,我无论如何都想设置该标志。

提前感谢任何能给我解决方案/想法的人。

方法在很大程度上取决于您想要在这里完成什么。但试图给出一个简单的答案:

事务被标记为仅回滚

意味着所有数据库资源的更改将在事务结束时回滚(而不是持久化(->在您的startBeggin方法结束时回滚。

因此,utilsService.setFlag中更改的任何数据库资源也将不会持久化->,因为当前事务已被标记为进行回滚。


为了避免这种情况,您需要在utilsService.setFlag上有一个新的事务@Transactional(propagation = Propagation.REQUIRES_NEW),该事务将与startBeggin方法中创建的事务隔离。

你还应该记住@Transactional何时工作:

https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html#transaction-声明性注释

最新更新