java - Spring 对异步事务方法的捕获错误进行操作

标签 java spring hibernate spring-transactions rollback

我已阅读 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),这将与在 startBeggin 方法中创建的事务隔离。

您还应该记住 @Transactional 何时起作用:

https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html#transaction-declarative-annotations

关于java - Spring 对异步事务方法的捕获错误进行操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60813421/

相关文章:

java - 将编译器与编辑器关联

java - 正则表达式匹配除图像名称和扩展名之外的所有内容

java - 使用组时 Spring Boot 2 剩余 validator 调用两次

java - 为休息服务构建 Spring 安全拦截器

mysql - 我无法查看我刚刚创建的表?我不明白为什么

java - 无法添加或更新子行: a foreign key constraint fails - One-To-Many relationship - Hibernate

java - 创建具有大型正文的 AXIOM SOAP 消息

java - 如何使用 Spring 以编程方式使用来自 Rest API 的文件?

java - 定义一个并发哈希集spring bean?

java - hibernate 错误: No Persistence provider for EntityManager named my-unit