Spring 在@Transactional 方法中捕获 JpaSystemException 并回滚事务

Spring Catch JpaSystemException in @Transactional Method and Roll Back Transaction

我有一个用

注释的方法
@Transactional(isolation = Isolation.SERIALIZABLE, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)

并调用多个存储库方法。现在,当一个存储库试图更改被锁定且未被该方法的另一个实例回滚的数据库行时,spring 正确地抛出

 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;
    }

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

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

执行 messageReceived() 方法后,将发生这两件事,并且在 @Transactional 级别抛出 JPA 异常,这意味着您需要从调用此方法的地方处理此异常(控制器;如果您从控制器)。 有关@Transactional 的更多信息,请参见 link.