15

現在、クライアントが特定のエンティティのほとんどのプロパティを簡単にフィルタするようにするREST APIを構築しています。 QueryDSLSpring Data RESTan example by Oliver Gierke)と組み合わせて使用​​すると、プロパティ(例:/users?firstName=Dennis&lastName=Laumen)を参照するクエリパラメータを組み合わせてクライアントがフィルタリングできるようにすることで、自分が望むものの90%を簡単に取得できます。SpringデータRESTのQueryDSL統合を使用してより複雑なクエリを実行できますか?

QuerydslBinderCustomizerインターフェイス(たとえば、大文字小文字を区別しない検索や部分文字列の一致など)を実装することで、クエリパラメータとエンティティのプロパティの間のマッピングをカスタマイズすることもできます。これはすべて素晴らしいですが、クライアントが範囲を使用していくつかのタイプをフィルタリングできるようにしたいと思います。例えば、生年月日のようなプロパティに関しては、私は次のようなものをしたいと思います。/users?dateOfBirthFrom=1981-1-1&dateOfBirthTo=1981-12-31同じことが数字ベースのプロパティの場合は/users?idFrom=100&idTo=200になります。私はこれがQuerydslBinderCustomizerインターフェイスを使って可能でなければならないと感じていますが、これら2つのライブラリの統合は非常に広範には書かれていません。

これは、Spring Data RESTとQueryDSLを使用すると可能ですか?もしそうなら、どうですか?

答えて

19

私はあなたが、これは、次のカスタマイズを使用して仕事を得ることができるはずだと思う:

bindings.bind(user.dateOfBirth).all((path, value) -> { 

    Iterator<? extends LocalDate> it = value.iterator(); 
    return path.between(it.next(), it.next()); 
}); 

ここで重要なのは、?dateOfBirth=…&dateOfBirth=(2回プロパティを使用)し、あなたを与える結合….all(…)を使用することです提供されたすべての値へのアクセス。

は春が正しく着信StringsLocalDateにインスタンスを変換することができるようにあなたがUserdateOfBirth -propertyに@DateTimeFormat注釈を追加していることを確認します。

ラムダは現在、個々の要素を解き放つ必要があるように、Collection<? extends T>を取得していますが、将来のリリースでこれを変更して、むしろListを公開することができます。

+0

ありがとう@ oliver-gierke!あなたが与えた例に基づいて動作するようにして、さらに条件付きのロジックを追加しました。そのため、日付が1つだけ指定されている場合は、「from」日付として使用されます。 バインディングに存在しないパスを追加することも可能ですか? SpringデータRESTとQueryDSLを使用して "dateOfBirthFrom"クエリパラメータを追加することも可能ですか? (ちょっと不思議なことに、私の問題はすでに解決済みです!ありがとうございます!) –

+1

@DennisLaumen "dateOfBirthFrom"スタイルのクエリパラメータが役立つかもしれません。クエリバインドのカスタマイズでは、日付が1つしかない場合は日付として使用されていると仮定します。しかし、これまでの日付を使用したフィルタリングは不可能です。どのような提案@ oliver-gierke? – gazal

+0

@gazal、次のコードを使用してこれを修正しました。 'bindings.bind(Date.class).ALL((DateTimePath パス、コレクション値)<日が延びる?> - > { イテレータ<日付を拡張>が(value.iteratorを=); 日firstTimestamp = it.next(); IF(it.hasNext()){ 日secondTimestamp = it.next(); 戻りpath.between(firstTimestamp、secondTimestamp); }他{ 戻りpath.after(firstTimestamp) ; } }); ' –

3

これは、すべての日付フィールドの汎用バインディングに使用したもので、常に2つの値が渡されます。

bindings.bind(Date.class).all((final DateTimePath<Date> path, final Collection<? extends Date> values) -> { 
    final List<? extends Date> dates = new ArrayList<>(values); 
    Collections.sort(dates); 
    if (dates.size() == 2) { 
     return path.between(dates.get(0), dates.get(1)); 
    } 
    throw new IllegalArgumentException("2 date params(from & to) expected for:" + path + " found:" + values); 
}); 

これはdatetimeフィールドです。日付フィールドの場合、単一のパラメータを取得する場合、path.eq()はわかります。

5

私はフィールド名creationDateFromcreationDateToに応じて異なる動作をする必要もありました。それを動作させるために、私は次のようにしました:

最初に@QueryEntity注釈と2つのフィールドをエンティティクラスに追加しました。フィールドがで注釈された:私たちはロンボクを使用しているようにフィールドは

  • @Getter(value = AccessLevel.PRIVATE)を永続化されません、注釈はレスポンスボディ
  • @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)から フィールドを隠し

    • @Transient構文解析するためのフォーマットの世話をしますURLクエリパラメータ

    @QueryEntity 
    @Entity 
    public class MyEntity implements Serializable { 
        ... 
    
        @Column(updatable = false) 
        @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) 
        private Date creationDate; 
    
        @Transient 
        @Getter(value = AccessLevel.PRIVATE) 
        @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) 
        private Date creationDateTo; 
    
        @Transient 
        @Getter(value = AccessLevel.PRIVATE) 
        @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) 
        private Date creationDateFrom; 
    
        ... 
    } 
    
    0に 日

    次に、querydslクラスを生成する方法をJPAAnnotationProcessorからQuerydslAnnotationProcessorに変更しました。この方法で@Transientと注釈を付けたフィールドはまだQMyEntityに生成されますが、永続化されません。ポンポンでのプラグインの設定:

    <plugin> 
        <groupId>com.mysema.maven</groupId> 
        <artifactId>apt-maven-plugin</artifactId> 
        <version>1.1.3</version> 
        <executions> 
         <execution> 
          <phase>generate-sources</phase> 
          <goals> 
           <goal>process</goal> 
          </goals> 
          <configuration> 
           <outputDirectory>target/generated-sources/annotations</outputDirectory> 
           <processor>com.querydsl.apt.QuerydslAnnotationProcessor</processor> 
          </configuration> 
         </execution> 
        </executions> 
    </plugin> 
    

    最後に、私はQuerydslBinderCustomizerを拡張し、creationDateFromcreationDateToに関連バインディングをカスタマイズしたが、あなたがすることができる。このすべての日付範囲でcreationDate

    @Override 
    default void customize(QuerydslBindings bindings, QMyEntity root) { 
        bindings.bind(root.creationDateFrom).first((path, value) -> 
                   root.creationDate.after(value)); 
        bindings.bind(root.creationDateTo).first((path, value) -> 
                   root.creationDate.before(value)); 
    } 
    

    上で右ロジックを適用しますクエリの1つ、両方、またはいずれも使用しないクエリ:

    http://localhost:8080/myentities?creation_date_to=2017-05-08 
    http://localhost:8080/myentities?creation_date_from=2017-01-01 
    http://localhost:8080/myentities?creation_date_from=2017-01-01&creation_date_to=2017-05-08 
    
  • 関連する問題