我需要在成功的事务提交之后做一些特定的操作,这基本上包括我对数据的分析操作;
我尝试使用以下代码段
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。
现在我已经通过将事件放入延迟队列来解决问题,并且延迟足以发生数据库提交。但我知道这不是一个好的解决方案。如果有人遇到此问题并能够解决问题,请告诉我。
提前致谢。
答案 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,那么你需要(至少):
默认行为将在提交完成后触发TransactionalEventListener&实体管理器已刷新,但仍在事务范围内。您可以使用'阶段'在注释中更改此设置。 param,但这应该足以解决你的问题。
PS。你可以从https://spring.io/blog/2015/02/11/better-application-events-in-spring-framework-4-2收集大部分内容,如JB Nizet所说