【问题标题】:jpa @postpersist @postupdate only after transaction commitjpa @postpersist @postupdate 仅在事务提交后
【发布时间】:2013-07-07 11:05:34
【问题描述】:

我在使用手动事务时插入/更新 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 方法? 如何在提交之后而不是在持久化之后调用方法?

【问题讨论】:

    标签: jpa jpa-2.0


    【解决方案1】:

    您可以使用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)。

    【讨论】:

    • 不错。您可以在 J2SE 应用程序中注册类似的处理程序吗?
    【解决方案2】:

    如果您处于 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 {}
    

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        猜你喜欢
        • 2011-06-21
        • 1970-01-01
        • 1970-01-01
        • 2016-10-23
        • 1970-01-01
        • 2015-12-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多