事务提交Spring JPA之后的事件

时间:2015-09-20 09:20:44

标签: hibernate spring-mvc java-ee jpa spring-transactions

我需要在成功的事务提交之后做一些特定的操作,这基本上包括我对数据的分析操作;

我尝试使用以下代码段

public class EntityEventHandlers {
    private static Logger logger = LoggerFactory.getLogger(EntityEventHandlers.class);

    @Autowired
    private AsyncEventBus async;

    @PostUpdate
    public void postUpdate(Order order) {
        AutowireHelper.autowire(this, this.async);
        logger.debug("post update called " + order.getId());
        async.post(new ESCreateOrderEvent(order));
    }

    @PostPersist
    public void postPersist(Order order) {
        AutowireHelper.autowire(this, this.async);
        logger.debug("post insert called " + order.getId());
        async.post(new ESCreateOrderEvent(order));
    }
}

但发现当我的订单没有坚持时。

有人可以告诉我一个更好的解决方案,我可以在事务提交成功后触发一些操作。

我听说(试过使用过)@TransactionEventListener,但没有看到任何触发。

  

更新了来源

@Component
public class TXEventHandler {
    @TransactionalEventListener
    public void doAfterCommit(ApplicationEvent event){
        //process here
    }
}

关于申请 它是一个基于4.2.0的Spring MVC,使用Hibernate和MySql作为db。

现在我已经通过将事件放入延迟队列来解决问题,并且延迟足以发生数据库提交。但我知道这不是一个好的解决方案。如果有人遇到此问题并能够解决问题,请告诉我。

提前致谢。

1 个答案:

答案 0 :(得分:6)

假设,正如您的评论所提到的,您正在使用实体管理器来持久化/合并您的实体对象,您可能有一个Bean连接它。如果是,那么为了利用@TransactionalEventListener,您希望ApplicationEventPublisher bean中的连线。你的课可能看起来像:

@Component
public class OrderManager {
    @PersistenceContext
    protected EntityManager entityManager;

    // You need this Spring bean
    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    // ...
    @Transactional
    public void saveOrder(Order newOrder) {
        entityManager.persist(newOrder);
        applicationEventPublisher.publishEvent(new OrderEvent());
    }

    @TransactionalEventListener
    public void doAfterCommit(OrderEvent event){
        //process here
    }

    // inner class for brevity, you may not want to do this in practice
    public static class OrderEvent {
    }   
}

这段代码(虽然可怕地放在一个单独的类中......)只是为了说明这一点:如果你想要触发@TransactionalEventListener,那么你需要(至少):

  1. 在Spring托管bean中定义它
  2. 连接" ApplicationEventPublisher"你的@Transactional居住的地方(在步骤1中不必是同一个bean)
  3. Call" applicationEventPublisher.publishEvent()"内部@Transactional方法
  4. 默认行为将在提交完成后触发TransactionalEventListener&实体管理器已刷新,但仍在事务范围内。您可以使用'阶段'在注释中更改此设置。 param,但这应该足以解决你的问题。

    PS。你可以从https://spring.io/blog/2015/02/11/better-application-events-in-spring-framework-4-2收集大部分内容,如JB Nizet所说

相关问题