返回一个计算结果为true的QueryDSL BooleanExpression

bal*_*teo 7 null querydsl

假设我有CustomerQueryInfo以下属性的bean:

  • String firstName
  • 字符串lastName
  • StatusEnum状态

我想使用此类型的对象执行" QueryDSL "搜索,该对象将返回客户列表List<Customer>.

如果其中一个字段CustomerQueryInfonull,我不想在搜索中使用它.因此CustomerQueryInfo,设置null了所有三个字段的对象将返回所有客户.

我正在寻找使用QueryDSL执行此类搜索的最佳实践.

这样的事情好吗:

private BooleanExpression isFirstNameLike(String firstName){
    if(firstName==null)
        return true BooleanExpression somehow;
    return QCustomer.customer.firstName.like(firstName);
}

private BooleanExpression isStatutEq(StatusEnum status){
    if(status==null)
        return true BooleanExpression somehow;
    return QCustomer.customer.status.eq(status);
}
Run Code Online (Sandbox Code Playgroud)

然后:

return query.from(customer).where(isFirstNameLike(customerQueryInfo.getFirstName).and(isLastNameLike(customerQueryInfo.getLastName).and(isStatusEq(customerQueryInfo.getStatus))).list;
Run Code Online (Sandbox Code Playgroud)
  1. 如何BooleanExpression将评估结果返回true?
  2. 如果不建议采用上述方法,那么建议的最佳做法是什么?

Fab*_*ney 21

如何返回计算结果为true的BooleanExpression?

BooleanExpression alwaysTrue = Expressions.asBoolean(true).isTrue();
Run Code Online (Sandbox Code Playgroud)

  • 似乎是一个很好的解决方案,但就我而言,我最终得到了 `java.lang.UnsupportedOperationException: Illegal operation true = true at com.querydsl.mongodb.MongodbSerializer.visit(MongodbSerializer.java:259` (3认同)
  • 实际上,“ BooleanBuilder”(请参见Lam Le的答案)最终运行良好。我一开始并没有意识到BooleanBuilder是谓词,因此一旦完成构建就可以将其直接传递给where子句。 (2认同)
  • @FabianBarney `Expressions.TRUE.isTrue()` 确实如此 (2认同)

Tim*_*per 20

您可以安全地使用这样的null谓词

private BooleanExpression isFirstNameLike(String firstName){
    return firstName != null ? customer.firstName.like(firstName) : null;        
}

private BooleanExpression isStatusEq(StatusEnum status){
    return status != null ? customer.status.eq(status) : null;
}
Run Code Online (Sandbox Code Playgroud)

并使用varargs方面的地方

query.from(customer)
     .where(
         isFirstNameLike(customerQueryInfo.getFirstName()),
         isLastNameLike(customerQueryInfo.getLastName()),
         isStatusEq(customerQueryInfo.getStatus()))
     .list(customer);
Run Code Online (Sandbox Code Playgroud)


小智 7

使用java 8和BooleanBuilder,您可以实现这样的优雅方式:

Java 8 Optional&Lambda

public final class ProductQuery {
    public static BooleanExpression nameEqualTo(String name){
        return ofNullable(name).map(QProduct.product.name::eq).orElse(null);
    }
}
Run Code Online (Sandbox Code Playgroud)

BooleanBuilder

BooleanBuilder where = new BooleanBuilder()
    .and(ProductQuery.nameEqualTo(name));
Run Code Online (Sandbox Code Playgroud)


pru*_*ule 5

我创建了一个QueryDSLHelper类,它具有静态方法,在添加表达式之前进行空值检查.像这样的东西:

public static void goe(BooleanBuilder builder, DateTimePath<Date> path, Date value) {
    if(date!=null) {
        builder.and(path.goe(value));
    }
}

public static void like(BooleanBuilder builder, StringPath path, String value) {
    if(value!=null) {
        builder.and(path.like(value));
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我可以静态导入这些方法并在一行上调用它们:

        like(builder, book.isbn, isbn);
Run Code Online (Sandbox Code Playgroud)

在实现'filter'或'filterByExample'查询时,这非常有用且非常干净/可读.

虽然,Timo的上述答案可能是更好的解决方案.