将Spring事务期间修改的JPA实体Bulkindexing转换为Elasticsearch索引

时间:2017-11-08 10:25:40

标签: jpa spring-data spring-data-jpa spring-transactions spring-data-elasticsearch

我有一个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。

感谢您的时间和帮助!

1 个答案:

答案 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