首页 > 解决方案 > Spring 在@Transactional 方法中捕获 JpaSystemException 并回滚事务

问题描述

我有一个带有注释的方法

@Transactional(isolation = Isolation.SERIALIZABLE, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)

并调用几个存储库方法。现在,当一个存储库尝试更改已锁定且未被该方法的另一个实例回滚的 DB 行时,sp​​ring 会正确抛出

 org.springframework.orm.jpa.JpaSystemException: could not execute statement [...] Caused by: java.sql.SQLException: transaction could not be serialized and rolls back the failed transaction.

现在我想保留所有这些行为,但另外处理异常并开始重试。这是一个代码片段:

@Transactional(isolation = Isolation.SERIALIZABLE, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    @Lock(LockModeType.PESSIMISTIC_WRITE)
    public void messageReceived(Card card) {
        this.request = request;
        this.numberOfAttempts = reset ? 0 : this.numberOfAttempts++;
        this.reset = true;
        LOGGER.info("Message received from Queue: " + card);
        TransactionDebugUtils.transactionRequired("MessageReceivedController.messageReceived");

        try {
            [...]
            repository1.createKonto(card);
            repository2.doStuff(card);

        } catch (JpaSystemException e) {
            //This is obviously never invoked
            LOGGER.error("TRANSACTION FAILED!!!");
        } catch (Exception e) {
            LOGGER.error("Error mapping json request to data model", message, e);
        }
    }

    @ExceptionHandler(JpaSystemException.class)
    //This is also never invoked
    public void handleJpaSystemException(JpaSystemException ex) {
        this.messageReceived(this.request);
        this.reset = false;
    }

标签: javaspringerror-handlingtransactional

解决方案


我最近有这个问题。由于它是一个方法级别的@Transactional 注解,所以事务提交是在​​方法执行完成之后发生的。当您使用此注释时,应考虑 2 个概念

  1. 持久性上下文
  2. 数据库事务

执行 messageReceived() 方法后,将发生这两件事,并且在 @Transactional 级别引发 JPA 异常,这意味着您需要从调用此方法的位置处理此异常(控制器;如果您从控制器调用)。更多关于 @Transactional 的信息可以在这个链接中找到。


推荐阅读