2017-08-18 6 views
1

私は現在、SpringデータJPAでSpringブートを使用してOracleデータベースに接続しています。一つのパラメータで私はSpringリポジトリfindById(Long id);を使っています。一方、検索はもっと複雑です。私たちの場合、ユーザーは複数のオプションの検索パラメータを入れ子にしたJSONオブジェクトを提供しています(この時点で、データの送信方法を入れ子にしたJSONを通して変更することはできません)。スプリングデータJPA複数のジョインによる複数のオプションの検索パラメータ

@Entity 
Account{ 
@OneToMany 
List<PersonRole> role; 

@OneToMany 
List<AgentRole> role; 
} 

@Entity 
PersonRole{ 
String role; 

Person person; 
} 

@Entity 
AgentRole{ 
String role; 

Agent agent; 
} 

@Entity 
Person{...} 

@Entity 
Agent{...} 
:我々は次のエンティティを持っているバックエンドでは

すべての検索条件は、(少なくとも1つのパラメータを除く)はオプションです

{ 
    "agent_filter": { 
    "first_name": "string", 
    "last_name": "string", 
    "agentNumber": "string", 
    "agentCode": "string" 
    }, 
    "account": "string", 
    "status": "string", 
    "paid": "string", 
    "amount": "string", 
    "person_filter": { 
    "date_of_birth": "string", 
    "first_name": "string", 
    "last_name": "string", 
    "tax_id": "string" 
    } 
} 

:ここではJSON入力オブジェクトは、次のようになります

検索機能を提供するために、私は複数の結合を行うことができます。 @Query表記でJPQ​​Lを使い始めましたが、各パラメータでis null orのチェックをしなければならず、大きな混乱が生じました。私は他のオプションを調べ始めて、QueryDSL、基準、仕様についての情報を見ましたが、どちらに焦点を当てて学ぶべきかはわかりませんでした。残念なことに、私はこのテーマについてはあまりよく分かりません。私は、この検索の優れた実装のために誰かが正しい方向に向けることを期待しています。ありがとうございました!

答えて

1

QueryDSLを好きなだけのparamを追加することができます!

...私はそれにあなたに非常によく似た問題を持っていたとき、私は私がフィルタリングしたかった原料の束を持っていたし、それらの多くはnullになる可能性があり、私は私のコードからあなたに例を挙げてみましょう

Btw、ファンシー結合が必要な場合は、おそらくquery dslを直接使用するつもりです。これらの例はQueryDSL 3のためのものですので、QueryDSL 4を変更する必要があります。検索機能を提供する方法を述べたので、おそらくQueryDSLを直接使用する必要があります。

まず、自分自身とBooleanBuilderを作成し、このような何か:だからあなたはあなたがフィルターに追加することができ、各フィールドを持っているか否かに基づいて

BooleanBuilder builder = new BooleanBuilder(); 
QContent content = QContent.content; 
if (contentFilter.headlineFilter == null || contentFilter.headlineFilter.trim().length() == 0) { 
     // no filtering on headline as headline filter = null or blank 
    } else if (contentFilter.headlineFilter.equals(Filter.NULL_STRING)) { 
     // special case when you want to filter for specific null headline 
     builder.and(content.label.isNull()); 
    } else { 
     try { 
      long parseLong = Long.parseLong(contentFilter.headlineFilter); 
      builder.and(content.id.eq(parseLong)); 
     } catch (NumberFormatException e) { 
      builder.and(content.label.contains(contentFilter.headlineFilter)); 
     } 
    } 
    if (contentFilter.toDate != null) { 
     builder.and(content.modifiedDate.loe(contentFilter.toDate)); 
    } 
    if (contentFilter.fromDate != null) { 
     builder.and(content.modifiedDate.goe(contentFilter.fromDate)); 
    } 

を。

これを機能させるには、com.mysema.query.apt.jpa.JPAAnnotationProcessor注釈プロセッサーを使用してQuery DSLメタデータを生成する必要があります。上記のQContent.contentを生成します。

BooleanBuilderはPredicateのサブクラスです。

+0

あなたの答えをありがとう、私はそれを調べ、すぐに試してみるつもりです。私はそれがどのように進むのかを知らせます。ありがとう! – ejgreenwald

+0

DSLをクエリすると@OneToManyリストでフィルタリングできますか?私の例を見ると、代理人のファーストネームでセレクトできますか?エージェントはリストの1つですが? – ejgreenwald

+0

これはおそらくジョインを必要とするため、クエリを作成するときに親と子の間で結合し、次にエージェントにフィルタを追加します。これを行う必要がある場合は、JpaRepositoryを使用することができません - QueryDSLを直接使用する必要があります。 –

1

独自の検索クエリを作成するには、カスタムクエリを使用する必要があります。

@Query("select u from User u where u.firstname = :#{#customer.firstname}") 
List<User> findUsersByCustomersFirstname(@Param("customer") Customer customer); 

は、今あなたがFTW

+0

ご回答ありがとうございます。それは間違いなく迅速かつ汚れたアプローチと私の現在の黙示ですが、非常に多くのオプションのパラメータがあるので、実際には醜いものになります。私が言及したように、私はパースを開始しなければならないか、それぞれによってヌルステートメントです。 – ejgreenwald

1

しかし、クエリdsl、条件、仕様は良好なアプローチですが、それらを学習する必要があります。

あなたの問題はJpaRepositoryを使って解決できます。 AccountRepositoryJpaRepositoryに拡張されており、もう一度QueryByExampleExecutorに拡張されている可能性があります。

QueryByExampleExecutorは、findOne(Example<S> example)findAll(Example<S> example)のようないくつかのメソッドを提供します。このメソッドは、渡したExampleオブジェクトに基づいて結果を返します。 Exampleの作成

Person person = new Person();       
person.setFirstname("Dave");       

Example<Person> example = Example.of(person); 

これは、よりSpring Data Query by Exampleで読むfirstName = Dave

を持つすべての人にマッチします簡単です。

+0

あなたの答えをありがとう。 Querybyexampleはリストで動作していないようです。 IE:新しい人物。 person.setFirstName( "Bob");新しいPersonRole personRole; personRole.add(人);新しいArrayList ()リスト; list.add(PersonRole)このコードでは、人の名前を検索しません。 – ejgreenwald

+0

例でクエリが参照されたエンティティに拡張できるとは思わない –

関連する問題