Spring 对异步事务方法的捕获错误进行操作
Spring make an operation on a catch error of an Asynchronus Transactional method
我已阅读 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) 中的操作之间发生的任何异常,将该值设置为那个物体?
如何在事务回滚(失败)时设置(或更新)对象上的字段?
事务方法影响的对象是相同的(通过 ID 恢复),但所有 roolbacked 操作都没有链接到我想设置的那个标志。
提前感谢任何能给我解决方案/想法的人。
该方法在很大程度上取决于您要在此处完成的任务。但试图给出一个简单的答案:
Transaction was marked for rollback only
意味着对数据库资源所做的所有更改都将在事务结束时回滚(不持久化)-> 在您的情况下,在您的 startBeggin 方法结束时。
因此,在 utilsService.setFlag
中更改的任何数据库资源也不会被持久化 -> 因为当前事务 已经标记 用于回滚。
为避免这种情况,您需要在 utilsService.setFlag
上创建一个新交易 @Transactional(propagation = Propagation.REQUIRES_NEW)
,它将与 [=27= 中创建的交易隔离开来]startBeggin 方法。
您还应该记住@Transactional 何时起作用:
我已阅读 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) 中的操作之间发生的任何异常,将该值设置为那个物体?
如何在事务回滚(失败)时设置(或更新)对象上的字段?
事务方法影响的对象是相同的(通过 ID 恢复),但所有 roolbacked 操作都没有链接到我想设置的那个标志。
提前感谢任何能给我解决方案/想法的人。
该方法在很大程度上取决于您要在此处完成的任务。但试图给出一个简单的答案:
Transaction was marked for rollback only
意味着对数据库资源所做的所有更改都将在事务结束时回滚(不持久化)-> 在您的情况下,在您的 startBeggin 方法结束时。
因此,在 utilsService.setFlag
中更改的任何数据库资源也不会被持久化 -> 因为当前事务 已经标记 用于回滚。
为避免这种情况,您需要在 utilsService.setFlag
上创建一个新交易 @Transactional(propagation = Propagation.REQUIRES_NEW)
,它将与 [=27= 中创建的交易隔离开来]startBeggin 方法。
您还应该记住@Transactional 何时起作用: