2011-02-04 107 views
11

我目前正在使用@PostPersist@PostUpdate,在这些触发器中,我坚持附加的实体。问题是,这些触发器是否在同一个事务中,如果不是,可以强制它吗?JPA/@PostPersist @PostUpdate - 交易

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

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

如果延长这个触发交易是不可能的,如何保证如果@PostPersist@PostUpdate前发生回退,这些操作也将rollbacked。

预先感谢您的任何帮助,

亲切的问候, P.

+0

嘿。当我测试时,我发现监听器中的所有操作都在主操作的同一事务中。我使用@PostUpdate注释来标记侦听器。 – Scarlett 2012-04-12 07:01:23

回答

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来标记其他实体应该被持久化并在另一个事务中执行。

10

如果你使用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

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

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