web-dev-qa-db-ja.com

Spring Dataで同じQueryDSLパスに複数のエイリアスを作成する

QuerydslBinderCustomizerを拡張する一般的なSpring Dataリポジトリインターフェイスを使用して、クエリの実行をカスタマイズできます。 Spring Data RESTを使用して他のクエリ操作を実行できるように、デフォルトのリポジトリ実装に組み込まれている基本的な等価テストを拡張しようとしています。例えば:

GET /api/persons?name=Joe%20Smith  // This works by default
GET /api/persons?nameEndsWith=Smith  // This requires custom parameter binding.

私が抱えている問題は、作成するエンティティパスのすべてのエイリアスが、前述のエイリアスバインディングをオーバーライドしているように見えることです。

@NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable>
    extends PagingAndSortingRepository<T, ID>, QueryDslPredicateExecutor<T>, QuerydslBinderCustomizer { 

    @Override
    @SuppressWarnings("unchecked")
    default void customize(QuerydslBindings bindings, EntityPath entityPath){

        Class<T> model = entityPath.getType();
        Path<T> root = entityPath.getRoot();
        for (Field field: model.getDeclaredFields()){
            if (field.isSynthetic()) continue;
            Class<?> fieldType = field.getType();
            if (fieldType.isAssignableFrom(String.class)){
                // This binding works by itself, but not after the next one is added
                bindings.bind(Expressions.stringPath(root, field.getName()))
                        .as(field.getName()  + "EndsWith")
                        .first((path, value) -> {
                            return path.endsWith(value);
                        });
                // This binding overrides the previous one
                bindings.bind(Expressions.stringPath(root, field.getName()))
                        .as(field.getName()  + "StartsWith")
                        .first((path, value) -> {
                            return path.startsWith(value);
                        });
            }
        }
    }
}

同じフィールドに複数のエイリアスを作成することはできますか?これは一般的な方法で実現できますか?

45
woemler

次のようにして、QueryDSLにバインドされた一時的なプロパティを作成できます。

@Transient
@QueryType(PropertyType.SIMPLE)
public String getNameEndsWith() {
    // Whatever code, even return null
}

QueryDSLアノテーションプロセッサを使用している場合は、メタデータQxxxクラスに「nameEndsWith」が表示されるため、永続化することなく、永続化プロパティのようにバインドできます。

1
apetrelli