【问题标题】:Spring with Query Dsl custom binding and or operation doesn't work带有 Querydsl 自定义绑定和或运算符的 Spring 不起作用
【发布时间】:2017-07-30 17:07:29
【问题描述】:

我有以下需求查询:

"/article?category=kitchen&category=sports"

此查询在没有自定义绑定的情况下工作。它会给我所有的厨房和体育文章作为回应。它正在以某种方式进行 OR 操作。

但我需要自定义绑定,因为我需要输入案例。现在我正在使用这个自定义绑定:

@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));
  }
}

这只会过滤属性的第一个可用值。因此,在这种情况下,它仅将厨房类别中的文章作为响应。类别(运动)的第二个值被忽略。

现在我的问题:我怎样才能得到 both 类别的文章而忽略大小写?我需要在自定义绑定中进行哪些更改才能实现这一目标?

非常感谢

【问题讨论】:

    标签: java spring filter binding querydsl


    【解决方案1】:

    QuerydslBindings.TypeBinder#first 使用single value binding。您需要使用 QuerydslBindings.TypeBinder#all。该方法在一个 multivalue binding.

    我在answer 中提供了几个如何自定义绑定的示例。像这样的东西应该适合你:

    @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) );
        });
    
    }
    

    【讨论】:

    • 实际上,对于您的示例,它不起作用。我不能使用 .all() 方法:QuerydslBindings.PathBinder 类型中的方法 all(MultiValueBinding) 不适用于参数(( path, 值)-> {})
    • 如果我没记错的话,它确实不适用于bind(Class&lt;T&gt; type) parameter,但它应该适用于bind(T... paths)
    • @EmreÖztürk 明确提到 StringPath 和 Collection extends String> 为 lambda 参数做的伎俩。
    【解决方案2】:

    article.category 属性的正确绑定应该是这样的:

    bindings.bind(article.category).all((path, value) -> {
        BooleanBuilder predicate = new BooleanBuilder();
        value.forEach(o -> predicate.or(path.equalsIgnoreCase(o)));
        return Optional.of(predicate);
    });
    

    如果您不需要对参数进行任何操作(例如忽略大小写),您可以将其简化为:

    bindings.bind(article.category).all((path, value) -> Optional.of(path.in(value)));
    

    【讨论】:

      【解决方案3】:

      经过一番搜索,我找到了解决方案。

       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;
              }
          });
      

      【讨论】:

      • 它说自定义没有实现抽象方法,它期望作为参数,而不是新的MultiValueBind、StringPath和Collection。
      猜你喜欢
      • 2020-01-12
      • 1970-01-01
      • 2012-02-28
      • 2017-02-14
      • 1970-01-01
      • 2017-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多