Specification接口里的toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb)
其中 Root是查询结果的一个实体对象,也就是查询结果返回的主要对象,其中一对多OR多对一就是从这个对象开始计算的,具体层级关系
javax.persistence.TupleElement<X>
javax.persistence.criteria.Selection<X>
javax.persistence.criteria.Expression<T>
javax.persistence.criteria.Path<X>
javax.persistence.criteria.From<Z, X>
javax.persistence.criteria.Root<X>
这几个接口主要用于描述一个数据库对象与实体对象的对应关系,就不多说了。
然后是javax.persistence.criteria.CriteriaQuery<T>,这个是JPA标准,主要是构建查询条件的,里面的方法都是各种查询方式:distinct、select、where、groupby、having、orderby这些方法,想必大家都知道这些是组件SQL语句的基本方法。
接下来是javax.persistence.criteria.CriteriaBuilder,这个接口主要是用来进行一些函数操作,不过我们这里先关注JPA标准中Hibernate的两个实现方法:
1.and org.hibernate.ejb.criteria.CriteriaBuilderImpl.and(Predicate...)
2.or org.hibernate.ejb.criteria.CriteriaBuilderImpl.or(Predicate...)
这两个方法都有一个关键的接口:Predicate(javax.persistence.criteria.Predicate);
这个接口,同为Expression(javax.persistence.criteria.Expression<Boolean>)的子接口,可以肯定也是字段相关的表达式,在实际操作中,这个接口也是作为关联各种Predicate的核心操作接口,and方法是将各个条件作为and来拼接,进行查询;or是将各条件作为or来拼接,进行查询。
然后说如何生成一个Predicate接口,生成的核心类还是上面的CriteriaBuilder(javax.persistence.criteria.CriteriaBuilder),在这个接口中,很多方法都是返回Predicate接口的,其中包含between、gt(大于)、lt(小于)、not(非)等等操作,将所需要的这些查询条件都放在一个array数组(或者采用java.util.ArrayList.toArray(T[])-->cb.and(predicateList.toArray(new Predicate[predicates.size()]))),然后调用上一步说的and或者or方法进行拼接,当然,如果一个查询既有and又有or,用这种方式还没有具体尝试过,有待考证。
Root:查询哪个表
CriteriaQuery:查询哪些字段,排序是什么
CriteriaBuilder:字段之间是什么关系,如何生成一个查询条件,每一个查询条件都是什么方式
Predicate(Expression):单独每一条查询条件的详细描述
/** 查询名字包含icarus,或者手机号包含188的用户(如果return中的or改为and,就是查询名字包含icarus,并且手机号包含188的用户) */
// query = cb.createQuery(User.class);// query是这么出来的
List<Predicate> predicateList = new ArrayList<>();
root = query.from(User.class);
Path<String> nameExp = root.get("name");
Predicate p1 = cb.like(nameExp, "%icarus%");
Path<String> phoneExp = root.get("phone");
Predicate p2 = cb.like(phoneExp, "%188%");
predicateList.add(p1);
predicateList.add(p2);
return cb.or(predicateList.toArray(new Predicate[predicates.size()]));