JPA / @PostPersist @PostUpdate - 交易

时间:2011-02-04 08:15:59

标签: java jpa transactions

我目前正在使用@PostPersist@PostUpdate,在这些触发器中,我会持续使用其他实体。问题是,这些触发器是否在同一个交易中,如果不是,是否可以强制它?

对我而言,它就是这样的。 当我查看日志时,事务不存在(它在触发器启动之前提交),这阻止了我(注入bean的持久化方法没有REQUIRES_NEW)保存数据库中的其他实体。 <{1}}属性完全被忽略,REQUIRED属性不会抛出异常。

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

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

3 个答案:

答案 0 :(得分:16)

如果您正在使用Spring,您可以随时向当前的事务管理器注册TransactionSynchronization,以便在诸如当前正在运行的事务的提交之类的事件上回调:

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

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

在事务成功提交后以及事务完成之前/之后,TransactionSynchronization还提供回调。

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

有关详细信息,请查看TransactionSynchronization's JavaDoc

答案 1 :(得分:11)

触发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
  }
}

注意:我没有尝试过,所以这只是推测(因为我已经广泛使用了生命周期事件触发器)。 我必须补充一点,我认为这不是一个好主意。使用PostPersist标记其他实体应该保留并在另一个事务中执行。

答案 2 :(得分:-3)

JPA内部回调方法 内部回调方法是在实体类中定义的方法。例如,以下实体类使用空实现定义所有支持的回调方法:

@Entity
public static class MyEntityWithCallbacks {
    @PrePersist void onPrePersist() {}
    @PostPersist void onPostPersist() {}
    @PostLoad void onPostLoad() {}
    @PreUpdate void onPreUpdate() {}
    @PostUpdate void onPostUpdate() {}
    @PreRemove void onPreRemove() {}
    @PostRemove void onPostRemove() {}
}

内部回调方法应始终返回void并且不带参数。它们可以具有任何名称和任何访问级别(公共,受保护,包和私有),但不应该是静态的。

注释指定何时调用回调方法:

@PrePersist - before a new entity is persisted (added to the EntityManager).
@PostPersist - after storing a new entity in the database (during commit or flush).
@PostLoad - after an entity has been retrieved from the database.
@PreUpdate - when an entity is identified as modified by the EntityManager.
@PostUpdate - after updating an entity in the database (during commit or flush).
@PreRemove - when an entity is marked for removal in the EntityManager.
@PostRemove - after deleting an entity from the database (during commit or flush).

实体类可以包括任何子集或生命周期事件组合的回调方法,但同一事件的回调方法不能超过一个。但是,通过使用多个注释标记多个回调事件,可以使用相同的方法。

默认情况下,还会为子类的实体对象调用超级实体类中的回调方法,除非子类重写该回调方法。

实施限制 为避免与触发实体生命周期事件(仍在进行中)的原始数据库操作发生冲突,回调方法不应调用EntityManager或Query方法,也不应访问任何其他实体对象。

如果回调方法在活动事务中抛出异常,则事务被标记为回滚,并且不再为该操作调用回调方法。