リポジトリのインターフェイスはJpaSpecificationExecutorを継承したとき、私たちは次のインターフェイスページングクエリを使用することができます。
/ ** * {返し@linkの所与{一致するエンティティのページ} @link 仕様}。 * * @paramの仕様は、{とすることができる@literal ヌル}。 * @paramのページング可能であってはならない{ @literal ヌル}。 * @return 決して{ @literal ヌル}。 * / ページ <T>のfindAll(@Nullable仕様<T>仕様、ページング可能ページング可能)。
バインディングJPA-specが簡単に仕様を構築することができます。
JPAスペックgithubの住所:https://github.com/wenhao/jpa-spec
パブリックページの<person> のfindAll(SearchRequestリクエスト){ 仕様 <人>仕様=仕様<者> と() .EQ(StringUtils.isNotBlank(request.getName())、 "名前" 、request.getName()) 。GT(Objects.nonNull(request.getAge())、 "年齢"、18 ) .between( "誕生日"、新しい日付()、新しい日付()) .like( "ニックネーム"、 "%OG%"、 " %私」) .build(); 戻り personRepository.findAll(仕様、新しい PageRequest(0、15 ))。
単一テーブルのクエリは、実際には非常に簡単ですが、複雑な問い合わせ、複合体の一部:
公共の一覧<電話番号> のfindAll(SearchRequestリクエスト){ 仕様 <電話>仕様=仕様。<電話> と() .EQ(StringUtils.isNotBlank(request.getBrand())、 "ブランド"、 "華為" ) .EQ( StringUtils.isNotBlank(request.getPersonName())、 "person.name"、 "ジャック" ) .build(); 戻りphoneRepository.findAll(仕様)。 }
ここでの携帯電話は、使用方法がperson.nameな条件を作るために人の名前を使用して、メインテーブルです。
内部JPA-specはperson.name、以下のコードを分析します:
公共 getRoot(Stringプロパティ、ルート<T>からルート){ 場合( "" property.contains( )){ 文字列joinProperty = StringUtils.split( ""プロパティ)[0 ]; リターンroot.join(joinProperty、JoinType.LEFT)。 } 他{ 戻りルート。 } }
あなたはそれがこのSQLを生成し、2つのフィールド条件が存在する場合、それが再び参加するでしょう、そして、問題がある、root.joinでそれを見ることができます:
外側左携帯電話から選択* XX = XX上の人物を参加者XX = XXを外部結合左。
これは確かに需要を満たしていません。また、バグJPA仕様のバーでなければなりません
この問題を解決するために、あなたはそれがクエリを提供する別の方法を使用することができます。
公共の一覧<電話番号> のfindAll(SearchRequestリクエスト){ 仕様 <人>仕様=仕様。<人> と() .between( "年齢"、10、35 ) .predicate(StringUtils.isNotBlank(jack.getName())、 ((ルート、クエリ、CB) - > { アドレス参加 = root.join( "アドレス" 、JoinType.LEFT)を、 リターン cb.equal(address.get( "ストリート")、 "成都" ); })) 。ビルド(); 戻りphoneRepository.findAll(仕様)。 }
このために、ページングに加えて、ほとんどのケースで解決することができます
通常の単一テーブルのクエリページング+並べ替えを見て:
パブリックページの<person> のfindAll(SearchRequestリクエスト){ 仕様 <人>仕様=仕様<者> と() .EQ(StringUtils.isNotBlank(request.getName())、 "名前" 、request.getName()) 。GT( "年齢"、18 ) .between( "誕生日"、新しい日付()、新しい日付()) .like( "ニックネーム"、 "%のOG%" ) .build(); ソートソート = Sorts.builder() .desc(StringUtils.isNotBlank(request.getName())、 "名前""誕生日" ) .build(); 返す personRepository.findAll(仕様、新しい PageRequestを(0、15 、ソート)); }
この関連付け、次のコードに基づいて増加する場合:
パブリックページの<person> のfindAll(SearchRequestリクエスト){ 仕様 <人>仕様=仕様<人> と() .predicate(StringUtils.isNotBlank(jack.getName())、((根、クエリ、CB) - > { アドレス参加 = root.join( "アドレス" 、JoinType.LEFT)を、 戻り cb.equal(address.get( "通り")、 "成都" ); })) .EQ(StringUtils.isNotBlank(request.getName() )、 "名前" 、request.getName()) .GT( "年齢"、18 ) 。(間の「誕生日」、新しい日付()、新しい日付()) .like( "ニックネーム"、 "%のOG%" ) .build(); ソートソート = Sorts.builder() .desc(StringUtils.isNotBlank(request.getName())、 "名前" ) .ASC( "誕生日" ) .buildを(); 返す personRepository.findAll(仕様、新しい PageRequestを(0、15 、ソート)); }
あなたは次のように解決策がある、クエリアドレス文の多くを生成するための遅延ロードの失敗のアドレスを検索します。
パブリックページの<person> のfindAll(SearchRequestリクエスト){ 仕様 <人>仕様=仕様<人> と() .predicate(StringUtils.isNotBlank(jack.getName())、((根、クエリ、CB) - > { ;アドレスに参加し た場合(ロングクラス!= query.getResultType()){ アドレス =(参加)root.fetch( "アドレス" 、JoinType.LEFT); } 他{ アドレス = root.join( "アドレス" 、JoinType。 LEFT); } 戻りcb.equal(address.get( "ストリート")、 "成都" ); })) .EQ(StringUtils.isNotBlank(request.getName())、 "名前" 、request.getName()) .GT( "年齢"、18 ) .between( "誕生日"、新しい日付()、新しい日付()) .like( "ニックネーム"、 "%のOG%" ) .build(); ソートソート = Sorts.builder() .desc(StringUtils.isNotBlank(request.getName())、 "名前" ) .ASC( "誕生日" 返す personRepository.findAll(仕様、新しい PageRequestを(0、15 、ソート)); }
この時点では、仕様のお問い合わせには十分なはずで、方法JpaRepository(SimpleJpaRepository)注釈と@query方法や基準のAPIクエリを提供と相まって、4つのJPAクエリは、ほとんどのアプリケーションのための問題を解決することができます。