JPA / @PostPersist @PostUpdate – 交易

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

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

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

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

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

 @PostPersist void onPersist() { TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() { @Override public void beforeCommit(boolean readOnly) { // do work } }); } } 

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

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

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

触发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标记应该保留其他实体并在另一个事务中执行。

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方法,也不应访问任何其他实体对象。

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