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

Posted

技术标签:

【中文标题】jpa @postpersist @postupdate 仅在事务提交后【英文标题】:jpa @postpersist @postupdate only after transaction commit 【发布时间】: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 方法? 如何在提交之后而不是在持久化之后调用方法?

【问题讨论】:

【参考方案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 事件。

【讨论】:

以上是关于jpa @postpersist @postupdate 仅在事务提交后的主要内容,如果未能解决你的问题,请参考以下文章

在 postPersist 事件中插入教义

使用 JPA 2.1、EclipseLink、JSF 2.0 的日志表

@PostPersist 中修改的字段未在数据库中更新

休眠错误在@PostPersist 方法中保留一个实体

Doctrine 2 - 如何在 PostPersist 中获取最后插入的 id 的 ID?

POST Update语句注入