【问题标题】:QueryDSL: convert list of BooleanExpression to PredicateQueryDSL:将 BooleanExpression 列表转换为 Predicate
【发布时间】:2015-09-01 08:27:43
【问题描述】:

我正在尝试创建一个取决于布尔参数数量的查询。创建谓词的函数如下所示:

Predicate createPredicate(Boolean param1, Boolean param2) {
    List<BooleanExpression> booleanExpressions = new List<>();        
    if (param1)
        booleanExpressions.add(/** expression 1 **/);
    if (param2)
        booleanExpressions.add(/** expression 2 **/);
    convertExpressionsToPredicate(booleanExpressions);
}

问题在于convertExpressionsToPredicate 函数。 querydsl 中是否有任何特殊方法可以使用or 运算符将表达式列表连接到一个谓词中?

我正在寻找的解决方案应该转换这个:

List<BooleanExpression> booleanExpressions = List(exp1, exp2, exp3);

进入:

Predicate p = exp1.or(exp2).or(exp3)

【问题讨论】:

    标签: java querydsl


    【解决方案1】:

    要构造复杂的布尔表达式,请使用com.querydsl.core.BooleanBuilder 类。它实现了Predicate,可以级联形式使用。例如:

    public List<Customer> getCustomer(String... names) {
        QCustomer customer = QCustomer.customer;
        JPAQuery<Customer> query = queryFactory.selectFrom(customer);
        BooleanBuilder builder = new BooleanBuilder();
        for (String name : names) {
            builder.or(customer.name.eq(name));
        }
        query.where(builder);
        return query.fetch();
    }
    

    BooleanBuilder 是可变的,最初表示 null。在每个andor 调用之后,它代表了操作的结果。

    【讨论】:

    • 请注意,如果给定的names 为空,BooleanBuilder() 将保持初始化而没有任何或条件,并且查询将获取所有客户。但是,在这种情况下,它应该不会返回任何客户。您可以使用!builder.hasValue() 进行检查,并使用空列表进行提前返回(或者在本示例的第一行中,有一个警卫检查names)。我还没有想出一个干净的方法来初始化 BooleanBuilder 所以它默认为“false”。
    【解决方案2】:

    如果有人在使用 Spring Boot JPA 和 QueryDSL,您可以使用以下命令获取 Page&lt;YourType&gt; 结果(在 Kotlin 中):

    fun listCards(page: Int?, pageSize: Int?, orderColumnName: String?, orderDirection: Sort.Direction?, filter: CardFilter?): Page<Card> {
      val pageRequest = PageRequest.of(page ?: 0, pageSize ?: 10, orderDirection ?: Sort.Direction.ASC, orderColumnName ?: Card::cardNumber.name)
      val conditions = BooleanBuilder()
      filter?.cardNumber?.let { qCard.cardNumber.contains(it) }?.let { conditions.and(it) }
      filter?.cardHolderName?.let { qCard.cardHolderName.containsIgnoreCase(it) }?.let { conditions.and(it) }
      filter?.phoneNumber?.let { qCard.phoneNumber.contains(it) }?.let { conditions.and(it) }
      filter?.email?.let { qCard.email.contains(it) }?.let { conditions.and(it) }
      filter?.locale?.let { qCard.locale.eq(it) }?.let { conditions.and(it) }
    
      if (conditions.hasValue()) {
        return cardRepository.findAll(conditions.value!!, pageRequest)
      }
      return cardRepository.findAll(pageRequest)
    }
    

    【讨论】:

      【解决方案3】:
      ExpressionUtils.allOf(ps) // use AND join conditions, ps is a list of predicate
      ExpressionUtils.anyOf(ps) // use OR join conditions, ps is a list of predicate
      

      【讨论】:

      • 在回答已有答案的旧问题时,请确保提供比现有答案更好的解释。
      • @Maritim 多年前回答的问题本身并不意味着不再允许新答案(否则无法发布新答案)。说“你的回答没有积极意义。” 也是相当不友好的,并且可能违反行为准则。该答案指向其他答案未提供的解决方案,因此它提供了一些新的东西。当然,这本来可以是一个更好的答案,但随后指出用户可以做得更好的地方(就像 Tyler2P 所做的那样)。
      • @MarkRotteveel 今后我会努力提供更好、更友好的反馈。
      猜你喜欢
      • 2017-12-03
      • 1970-01-01
      • 2021-09-21
      • 2013-05-26
      • 2013-05-15
      • 2014-10-19
      • 2012-08-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多