简体   繁体   English

Criteria query combine and predicates and or 谓词在 where 方法中

[英]Criteria query combine and predicates and or predicates in where method

The where method of CriteriBuilder CriteriBuilder的where方法

restricts the query result according to the conjunction of the specified restriction predicates根据指定的限制谓词的合取来限制查询结果

In other words, concatenate all predicates with AND.换句话说,用 AND 连接所有谓词。 I pass a list of predicates to this method in this way:我以这种方式将谓词列表传递给此方法:

criteria.where(preds.toArray(new Predicate[0]));

The result query is something like this:结果查询是这样的:

... where p1 and p2 and p3

however what I need is:但是我需要的是:

... where p1 and p2 or p3

I tried to use two list of preds, one for "ANDS" and another one for "ORS":我尝试使用两个预测列表,一个用于“ANDS”,另一个用于“ORS”:

if(preds.isEmpty() && !orPreds.isEmpty()) {
    criteria.where(cb.or(orPreds.toArray(new Predicate[orPreds.size()])));
}
else if(!preds.isEmpty() && !orPreds.isEmpty()) {
    criteria.where(cb.and(preds.toArray(new Predicate[preds.size()])), 
    cb.or(orPreds.toArray(new Predicate[orPreds.size()])));
}
else {
    criteria.where(preds.toArray(new Predicate[0]));
}

But the result query is the same:但是结果查询是一样的:

... where p1 and p2 and p3

Any idea?任何的想法?

Simply combine your arrays of predicates into simple predicates, using CriteriaBuilder.and(Predicate... restrictions) and CriteriaBuilder.or(Predicate... restrictions) 只需使用CriteriaBuilder.and(Predicate... restrictions)CriteriaBuilder.or(Predicate... restrictions)将谓词数组组合为简单谓词

For getting where (p1 and p2) or p3 , where p1 , p2 and p3 are all arrays of predicates concatenated with and statements: 为了获得where (p1 and p2) or p3 ,其中p1p2p3都是与and语句连接的谓词数组:

Predicate[] p1 = new Predicate[2];
Predicate[] p2 = new Predicate[2];
Predicate[] p3 = new Predicate[2];
// add your predicates to the arrays.     
Predicate p1all = cb.and(p1);    
Predicate p2all = cb.and(p2);
Predicate p3all = cb.and(p3);
Predicate pFinal = cb.or(cb.and(p1all, p2all), p3all);
criteria.where(pFinal);

For getting where p1 and (p2 or p3) : 为了获得where p1 and (p2 or p3)

Predicate pFinal = cb.and(cb.or(p2all, p3all), p1all);
criteria.where(pFinal);

Finally, if you want to build a single predicate by concatenating an array of predicates with or statements, use this: 最后,如果要通过将谓词数组与or语句连接来构建单个谓词,请使用以下命令:

Predicate p1all = cb.or(p1); 

By default all predicates are understood as "AND".默认情况下,所有谓词都被理解为“AND”。

You can "play" adding more complexity to the predicates using cb.and / cb.or (nested if needed)您可以“玩”使用 cb.and / cb.or 为谓词增加更多复杂性(如果需要嵌套)

You can create a list like this:您可以像这样创建一个列表:

Root<BeanA> queryRoot = cq.from(BeanA.class);

List<Predicate> predicates = new ArrayList<>();
predicates.add(cb.equal(queryRoot.get("id"), valueA);
predicates.add(cb.or(
                cb.equal(queryRoot.get("id"), valueA,
                cb.equal(queryRoot.get("id"), valueB
        ));
predicates.add(cb.and(
       cb.equal(queryRoot.get("valueC"), valueC),
       cb.or(
             cb.equal(queryRoot.get("id"), valueA,
             cb.equal(queryRoot.get("id"), valueB
        ))
);

cq.where(predicates.toArray(Predicate[]::new));

If needed, you can use a multiselect too (adding here the result of subqueries if you want to handle them)如果需要,您也可以使用多选(如果要处理子查询,请在此处添加子查询的结果)

 List<Selection> selectList = new ArrayList<>();

 selectList.add(queryRoot.get("id"));
 selectList.add(queryRoot.get("title"));

 cq.multiselect(selectList.toArray(Selection[]::new));

After adding a multiselect you could need an orderBy.添加多选后,您可能需要一个 orderBy。 you can follow the same concept but using a Expression list您可以遵循相同的概念,但使用表达式列表

List<Expression> groupByList = new ArrayList<>();

groupByList.add(proyectoJoin.get("id"));
groupByList.add(proyectoJoin.get("title"));
 
cq.groupBy(groupByList.toArray(Expression[]::new));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM