0

私は、ElasticsearchドキュメントでもあるJPAエンティティクラスを持っています。この環境は、Spring Data JpaとSpring Data Elasticsearchを使用したSpring Bootアプリケーションです。Springのトランザクション中にElasticsearchインデックスに変更されたJPAエンティティを一括検索する

@Entity 
@Document(indexname...etc) 
@EntityListeners(MyJpaEntityListener.class) 
public class MyEntity { 
    //ID, constructor and stuff following here 
} 

このエンティティのインスタンスが作成、更新、または削除されると、Elasticsearchに再インデックスされます。これは現在、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単一または少数のエンティティが単一のトランザクション中に変更されます現時点では、すべての作業罰金。各変更により、別々の索引操作がトリガーされます。しかし、多くのエンティティがトランザクション内で変更された場合、トランザクションは遅くなります。

トランザクションの終了時(またはコミット後)に変更されたすべてのエンティティをbulkindexしたいとします。私はTransactionalEventListeners、AOP、TransactionSynchronizationManagerを見ていましたが、これまでのところ良い設定を思いついたわけではありませんでした。

どのようにして、すべての変更されたエンティティをトランザクションごとにエレガントに収集することができますか?

また、トランザクションの最後に、このトランザクションの収集されたエンティティを使用してバルクインデックスをトリガーできます。

あなたの時間と助けてくれてありがとう!

答えて

0

あなたのサービスとエンティティをelasticsearch関連のコードと混在させないように、私の意見ではエレガントなアプローチは、サービスレイヤのトランザクションメソッドで@AfterReturningを使用することです。

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があります。

+0

あなたの考えに感謝します。私は、異なるサービスの異なるメソッドパラメータからすべてのエンティティを取得できるロジックを作成できるかどうかは疑問です。たとえば、フィールドXの特定の値を持つすべてのエンティティを削除するメソッド。これらのエンティティはなくなります。アスペクトを使用して保存をトリガーするという考えは、私の意見では良いことです。私の問題はエンティティをアスペクトにする方法でした。 @TransactionalEventListenerでアノテーションされたメソッドを実装し、JpaEventListenerに応じたイベントをパブリッシュするという考えを熟考しました。 –

+0

findByを使用してdeleteメソッドを調整して、サービスメソッド内のIdおよびdeleteByIdsを取得できます。この方法ではメソッドのパラメータとしてIDを取得します。私はdeleteBySomtething Spring Dataメソッドを使用しても内部的にはCrudRepository#を削除し、afterall..soというエンティティをロードしますが、とにかくパフォーマンスの低下は予想されません。我々の実装では、関連する弾性検索文書にデータベースIDも格納します。これは、さまざまなケースで役立つことが判明しました。そのうちの1つは、必要な文書を簡単に削除できることです。 – ltsallas

関連する問題