在Spring Data JPA相关的文章[地址]中提到了有哪几种方式可以构建Specification的实例,该处需要借助CriteriaBuilder,回顾一下Specification中toPredicate方法的定义,代码如下:
/\*\*
\* Creates a WHERE clause for a query of the referenced entity in form of a {@link Predicate} for the given
\* {@link Root} and {@link CriteriaQuery}.
\*
\* @param root must not be {@literal null}.
\* @param query must not be {@literal null}.
\* @param criteriaBuilder must not be {@literal null}.
\* @return a {@link Predicate}, may be {@literal null}.
\*/
@Nullable
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder);
CriteriaBuilder接口定义在包路径javax.persistence.criteria下,代码如下:
/**
* Used to construct criteria queries, compound selections,
* expressions, predicates, orderings.
*
*
Note that Predicate
is used instead of Expression<Boolean>
* in this API in order to work around the fact that Java
* generics are not compatible with varags.
*
* @since 2.0
*/
public interface CriteriaBuilder {
CriteriaBuilder中的一些方法如下图所示:
解读:
(1)CriteriaBuilder中的方法分为几个类别,譬如:ordering、aggregate functions、subqueries、equality、comparisons等等。
(2)CriteriaBuilder中的方法的返回值主要有CriteriaQuery、Expression、Predicate等几种类型。
观察CriteriaBuilder中and方法与or方法的定义,如下:
/\*\*
\* Create a conjunction of the given boolean expressions.
\* @param x boolean expression
\* @param y boolean expression
\* @return and predicate
\*/
Predicate and(Expression<Boolean> x, Expression<Boolean> y);
/\*\*
\* Create a conjunction of the given restriction predicates.
\* A conjunction of zero predicates is true.
\* @param restrictions zero or more restriction predicates
\* @return and predicate
\*/
Predicate and(Predicate... restrictions);
/\*\*
\* Create a disjunction of the given boolean expressions.
\* @param x boolean expression
\* @param y boolean expression
\* @return or predicate
\*/
Predicate or(Expression<Boolean> x, Expression<Boolean> y);
/\*\*
\* Create a disjunction of the given restriction predicates.
\* A disjunction of zero predicates is false.
\* @param restrictions zero or more restriction predicates
\* @return or predicate
\*/
Predicate or(Predicate... restrictions);
解读:
上述and方法与or方法用于组合多个查询条件。
其中Predicate and(Predicate… restrictions);方法使用不定数参数Predicate… restrictions,使用and连接词连接起来,通常可以传入多个Predicate参数,最佳实践是传入一个数组。
具体案例——添加多个查询条件
private Specification createSpecification(Integer specialId, String specialEmail) {
Specification
@Override
public Predicate toPredicate(Root
Path id = root.get("id");
Predicate predicateId = cb.gt(id, specialId);
Path email = root.get("email");
Predicate predicateEmail = cb.equal(email, specialEmail);
return cb.and(predicateId, predicateEmail);
}
};
return specification;
}
解读:
上述着色处代码以and方法将两个条件组合在一起
从前面的分析可知,CriteriaBuilder中的很多方法接受Expression或者Predicate类型的参数,并返回Expression或者Predicate类型的结果,譬如上面提到的and方法,所以本小节来探寻一下Expression与Predicate之间的关系。
Expression与Predicate之间的关系如下图所示:
解读:
Predicate接口继承了Expression接口,所以CriteriaBuilder中接受Expression类型参数的方法(譬如:and方法等)可以接受Predicate类型的参数,正如前面示例所展示的那样。
Note:
Path接口也继承了Expression接口,所以CriteriaBuilder中接受Expression类型参数的方法(譬如:lt方法)可以接受Path类型实例:
Specification<User> specification = new Specification<>() {
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Path<Integer> path = root.get("id");
return cb.lt(path, id);
}
};
解读:
上述示例在构造了Path类型的变量后调用了lt方法,该方法的定义如下:
/\*\*
\* Create a predicate for testing whether the first argument is
\* less than the second.
\* @param x expression
\* @param y value
\* @return less-than predicate
\*/
Predicate lt(Expression<? extends Number> x, Number y);
手机扫一扫
移动阅读更方便
你可能感兴趣的文章