jpa @postpersist @postupdate仅在事务提交后

时间:2013-07-07 11:05:34

标签: jpa jpa-2.0

我在使用手动交易时插入/更新3个表。我想在事务提交后立即插入历史表。这意味着有3 em.persist个动作(对于每个表),并且只有在提交它们之后我才想调用一个方法。

这是我的代码:

@Resource
private EJBContext context;

public void save(Object obj)
{
    try 
    {     
        transaction = context.getUserTransaction();
        transaction.begin();

        em.persist(obj);

        sb2.save(obj);  //persist in  sb2                         
        sb3.save(obj);  //persist in  sb2                         

        transaction.commit(); 
    }
    catch (Exception exp) 
    {
       transaction.rollback();        
    }   
 }

有任何类型的post commit方法吗? 如何在提交后调用方法,而不是在持久化之后?

3 个答案:

答案 0 :(得分:0)

JPA不提供此类事件,但EclipseLink通过SessionEventListener API提供扩展事件。

http://eclipse.org/eclipselink/documentation/2.5/jpa/extensions/p_session_event_listener.htm

您还可以考虑容器JTA事件。

答案 1 :(得分:0)

您可以使用TransactionSynchronizationRegistry注册要在事务完成后执行的回调:

public class MyListener {

    // if you can't inject it with @Resource, you'll have to fetch it from JNDI
    @Resource
    private javax.transaction.TransactionSynchronizationRegistry registry;

    @PostUpdate
    public void postUpdate(final Object entity) {
        registry.registerInterposedSynchronization(new Synchronization() {

            public void beforeCompletion() {}

            public void afterCompletion(int status) {
                if (status == javax.transaction.Status.STATUS_COMMITTED) {
                    // Do something with your entity
                }
            }
        });
    }
}

然后使用@EntityListeners(MyListener.class)为您的实体添加注释(或将其添加到您的orm.xml中)。

答案 2 :(得分:0)

如果您在JPA 2.2 + CDI + JTA环境中,则可以利用在指定的事务阶段可以观察到的CDI事件。

@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface EntityEvent {}

public class MyListener {

    @Inject
    @EntityEvent
    private Event<Object> event;

    @PostUpdate
    public void postUpdate(Object entity) {
        event.fire(entity);
    }
}

public class MyObserver {

    public void afterCommit(@Observes(during = TransactionPhase.AFTER_SUCCESS) @EntityEvent Object entity) {
        // do something...
    }
}

@EntityListeners(MyListener.class)
public class MyEntity {}