简体   繁体   English

在Spring事务中将JPA实体批量索引修改为Elasticsearch索引

[英]Bulkindexing JPA Entities modified during Spring transaction to Elasticsearch index

I have an JPA Entity Class that is also an Elasticsearch Document. 我有一个JPA实体类,它也是一个Elasticsearch文档。 The enviroment is a Spring Boot Application using Spring Data Jpa and Spring Data 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
}

When an instance of this Entity gets created, updated or deleted it gets reindexed to Elasticsearch. 创建,更新或删除此实体的实例时,会将其重新索引到Elasticsearch。 This is currently achieved with an JPA EntityListener which reacts on PostPersist, PostUpdate and PostRemove events. 当前,这是通过对PostPersist,PostUpdate和PostRemove事件做出反应的JPA EntityListener来实现的。

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
    }
}

That´s all working fine at the moment when a single or a few entities get modified during a single transaction. 当在单个事务中修改单个或几个实体时,一切都很好。 Each modification triggers a separate index operation. 每次修改都会触发单独的索引操作。 But if a lot of entities get modified inside a transaction it is getting slow. 但是,如果许多实体在事务内被修改,它将变得很慢。

I would like to bulkindex all entities that got modified at the end (or after commit) of a transaction. 我想对在事务结束时(或提交后)修改过的所有实体进行批量索引。 I took a look at TransactionalEventListeners, AOP and TransactionSynchronizationManager but wasn´t able to come up with a good setup till now. 我看了一下TransactionalEventListeners,AOP和TransactionSynchronizationManager,但是到目前为止,还没有一个好的设置。

How can I collect all modified entities per transaction in an elegant way without doing it per hand in every service method myself? 如何以一种优雅的方式收集每个事务的所有已修改实体,而无需自己亲自处理每种服务方法?

And how can I trigger a bulkindex at the end of a transaction with the collected entities of this transaction. 以及如何在事务结束时使用该事务的已收集实体触发bulkindex。

Thanks for your time and help! 感谢您的时间和帮助!

One different and in my opinion elegant approach, as you don't mix your services and entities with elasticsearch related code, is to use spring aspects with @AfterReturning in the service layer transactional methods. 我不认为服务和实体与Elasticsearch相关代码混合使用,这是一种与众不同的优雅方法,即在服务层事务处理方法中将spring方面与@AfterReturning一起使用。

The pointcut expression can be adjusted to catch all the service methods you want. 可以调整切入点表达式以捕获所需的所有服务方法。

@Order(1) guaranties that this code will run after the transaction commit. @Order(1)保证该代码将在事务提交后运行。

The code below is just a sample...you have to adapt it to work with your project. 下面的代码只是一个示例...您必须对其进行调整以适合您的项目。

@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);
    }
}

And here is an example with a logging aspect. 这是一个有关日志记录方面的示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM