问题
i have following reQuirement Query:
"/article?category=kitchen&category=sports"
This Query is working without custom bindings. It will give me all Kitchen and sports articles as Response. It is doing an OR-Operation somehow.
But i need to customize the binding because i need to ingore the case. Now i am using this customize binding:
@Repository
public interface ArticleRepository extends JpaRepository<Article, Long>,
QueryDslPredicateExecutor<QArticle>, QuerydslBinderCustomizer<QArticle> {
@Override
default public void customize(QuerydslBindings bindings, QArticle article) {
bindings.bind(String.class).first((StringPath path, String value) -> path.containsIgnoreCase(value));
}
}
This only filters the first available value of a attribut. So in this case it only gives articles in category kitchen as Response. The second value of the category (sports) is ignored.
And now my Question: How can i get the articles of both catergories ignoring the case sensetive? What i need to change in my customize binding to achieve that?
Thank you very much
回答1:
QuerydslBindings.TypeBinder#first uses a single value binding. You need to use QuerydslBindings.TypeBinder#all. This method operates on a multivalue binding.
I provided several examples of how to customize your bindings in this answer. Something like this should work for you:
@Override
default public void customize(QuerydslBindings bindings, QArticle article) {
// using explicit path bindings
bindings.bind(article.category).all((path, values) -> {
BooleanBuilder predicate = new BooleanBuilder();
// with a for loop
for (String value : values) {
predicate.or(path.containsIgnoreCase(value));
}
});
// using a type binding
bindings.bind(String.class).all((StringPath path, Collection<? extends String> values) -> {
BooleanBuilder predicate = new BooleanBuilder();
// oneliner with Java 8 forEach
values.forEach( value -> predicate.or(path.containsIgnoreCase(value) );
});
}
回答2:
The correct bindings for your article.category
property should be like this:
bindings.bind(article.category).all((path, value) -> {
BooleanBuilder predicate = new BooleanBuilder();
value.forEach(o -> predicate.or(path.equalsIgnoreCase(o)));
return Optional.of(predicate);
});
If you don't need any manipulations of the parameters (like ignoring case) you can simplify it to that:
bindings.bind(article.category).all((path, value) -> Optional.of(path.in(value)));
回答3:
After a good search on it I found the solution.
bindings.bind(String.class).all(new MultiValueBinding<StringPath, String> () {
@Override
public Predicate bind(StringPath path, Collection<? extends String> values) {
BooleanBuilder predicate = new BooleanBuilder();
values.forEach( value -> predicate.or(path.containsIgnoreCase(value)));
return predicate;
}
});
来源:https://stackoverflow.com/questions/42700008/spring-with-query-dsl-custom-binding-and-or-operation-doesnt-work