我有一个JPA实体类,它也是一个Elasticsearch文档。环境是使用Spring Data Jpa和Spring Data Elasticsearch的Spring Boot应用程序。
@Entity
@Document(indexname...etc)
@EntityListeners(MyJpaEntityListener.class)
public class MyEntity {
//ID, constructor and stuff following here
}
当创建,更新或删除此实体的实例时,它会重新编制索引到Elasticsearch。目前,这是通过JPA EntityListener实现的,它对PostPersist,PostUpdate和PostRemove事件作出反应。
public class MyJpaEntityListener {
@PostPersist
@PostUpdate
public void postPersistOrUpdate(MyEntity entity) {
//Elasticsearch indexing code gets here
}
@PostRemove
public void postPersistOrUpdate(MyEntity entity) {
//Elasticsearch indexing code gets here
}
}
在单个事务中修改单个或几个实体时,这一切都正常。每个修改都会触发单独的索引操作。但是如果在事务中修改了很多实体,那么它就会变慢。
我想对在事务结束时(或提交后)修改的所有实体进行bulkindex。我看了一下TransactionalEventListeners,AOP和TransactionSynchronizationManager,但到目前为止还没有能够提供良好的设置。
我怎样才能以优雅的方式收集每笔交易的所有修改过的实体,而不是自己在每个服务方法中单手操作?
如何在交易结束时使用此交易的收集实体触发bulkindex。
感谢您的时间和帮助!
答案 0 :(得分:0)
一种不同的,在我看来优雅的方法,因为你没有将你的服务和实体与elasticsearch相关的代码混合,就是在服务层事务方法中使用带有@AfterReturning的spring方面。
可以调整pointcut expression以捕获您想要的所有服务方法。
@Order(1)保证此代码将在事务提交后运行。
以下代码只是一个示例......您必须调整它以适应您的项目。
@Aspect
@Component()
@Order(1)
public class StoreDataToElasticAspect {
@Autowired
private SampleElasticsearhRepository elasticsearchRepository;
@AfterReturning(pointcut = "execution(* com.example.DatabaseService.bulkInsert(..))")
public void synonymsInserted(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
//create elasticsearch documents from method params.
//can also inject database services if more information is needed for the documents.
List<String> ids = (List) args[0];
//create batch from ids
elasticsearchRepository.save(batch);
}
}
这是一个带有日志记录方面的example。