JPA / @PostPersist @PostUpdate - 交易

2022-09-02 12:17:22

我目前正在使用 和 ,在这些触发器中,我保留了其他实体。问题是,这些触发器是否在同一笔交易中,如果没有,是否有可能强制它?@PostPersist@PostUpdate

对我来说,它以这种方式工作。当我查看日志时,事务不存在(它在触发器启动之前提交),这会阻止我(没有注入bean的持久化方法)将其他实体保存在数据库中。 属性被完全忽略,并且属性不会引发异常。REQUIRES_NEWREQUIREDMANDATORY

这可能是JUnit的问题吗(因为我处于开发阶段,没有在完整的环境中测试行为)?

如果无法在此触发器上扩展事务,如何确保如果回滚发生在 和 之前,这些操作也会被回滚。@PostPersist@PostUpdate


答案 1

如果你正在使用Spring,你可以随时向当前事务管理器注册一个,以便在事件(例如当前正在运行的事务的提交)上回调:TransactionSynchronization

@PostPersist
void onPersist() {
    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {

      @Override
      public void beforeCommit(boolean readOnly) {
        // do work
      }
    });
  }    
}

A 还提供在事务成功提交之后和事务完成之前/之后的回调。TransactionSynchronization

如果需要检查事务是否已提交或回滚,请使用 。afterCompletion(int status)

有关详细信息,请查看TranschangeSynchronization的JavaDoc


答案 2

触发 PostPersist 事件并不表示实体已完成成功的提交。事务可能会在事件触发后但在成功提交之前回滚。如果你在 PostPersist 中获取事务中使用的实体管理器,然后执行如下操作:

@PostPersist
void someMethod() {
  EntityManager em = null;
  em = getEntityManagerUsedInTransaction();
  EntityTransaction et = em.getTransaction(); // should return the current transaction
  if (et.isActive() ) {
    // do more db stuff
  }
}

NB:我还没有尝试过这个,所以这只是推测(我已经将生命周期事件触发器广泛用于其他事情)。我必须补充一点,我不认为这是一个好主意。使用 PostPersist 标记其他实体应持久化并在另一个事务中执行此操作。


推荐