12

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

  • 字符串名
  • 字符串姓氏
  • Status枚举状态

我想使用此类型的对象执行“ QueryDSLList<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);
}

然后:

return query.from(customer).where(isFirstNameLike(customerQueryInfo.getFirstName).and(isLastNameLike(customerQueryInfo.getLastName).and(isStatusEq(customerQueryInfo.getStatus))).list;
  1. 我如何返回一个BooleanExpression评估为真的?
  2. 如果上述方法不可取,那么推荐的最佳做法是什么?
4

5 回答 5

32

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

BooleanExpression alwaysTrue = Expressions.asBoolean(true).isTrue();
于 2017-10-09T17:25:28.500 回答
22

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

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

并使用 where 的可变参数方面

query.from(customer)
     .where(
         isFirstNameLike(customerQueryInfo.getFirstName()),
         isLastNameLike(customerQueryInfo.getLastName()),
         isStatusEq(customerQueryInfo.getStatus()))
     .list(customer);
于 2012-09-05T17:51:48.803 回答
8

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

Java 8 可选和 Lambda

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

布尔构建器

BooleanBuilder where = new BooleanBuilder()
    .and(ProductQuery.nameEqualTo(name));
于 2017-05-01T16:27:47.813 回答
6

我创建了一个 QueryDSLHelper 类,该类具有在添加表达式之前执行 null 检查的静态方法。像这样的东西:

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

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

        like(builder, book.isbn, isbn);

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

虽然,蒂莫的上述答案可能是更好的解决方案。

于 2014-06-13T01:34:56.140 回答
1

你可以这样做:

private BooleanExpression isFirstNameLike(String firstName){
    final QCustomer customer = QCustomer.customer;
    return customer.firstName.isNull().or(customer.firstName.like(firstName));
}

private BooleanExpression isStatutEq(StatusEnum status){
    final QCustomer customer = QCustomer.customer;
    return customer.status.isNull().or(customer.status.eq(status));    
}

或者,如果您想真正匹配firstName和/或状态,请更改

.isNull().or(...) to isNotNull().and(...)
于 2018-11-23T09:18:53.040 回答