三 Spring Data JPA进阶
3.1 动态查询
上述查询中,查询条件固定,导致每个查询条件都对应一个专门的方法,如:根据名称查询、根据地址查询、根据年龄查询。动态查询,指可以将查询条件作为参数,动态地选择查询条件。动态查询基于JpaSpecificationExecutor接口。
3.1.1 动态查询的接口和类
JpaSpecificationExecutor包括的查询接口:
查询单个:findOne(Specification<T> spec),返回T
查询列表:findAll(Specification<T> spec),返回List<T>
分页查询:findAll(Specification<T> spec, Pageable pageable),返回Page<T>
结果排序:findAll(Specification<T> spec, Sort sort),返回List<T>
统计查询:count(Specification<T> spec),返回Long
Specification:查询条件接口
需要自定义Specification接口的实现类,实现方法:
Predicate toPredicate(Root\<T> root, CriteriaQuery<?> query, CriteriaDuilder cb);
root:查询的根对象,
CriteriaQuery:顶层查询对象,自定义查询方式,一般不使用;
CriteriaBuilder:查询的构造器,封装查询条件;
3.1.2 动态查询的API
动态查询步骤:
1.定义接口;
2.创建Specification实现类对象,并定义查询规则;
3.查询,获取结果;
接口:
public interface CustomerDao extends JpaRepository<Custormer,Long>,JpaSpecificationExecutor<Customer>{
}
(1)findOne(Specification<T> spec)
调用
public void testSpec(){
// 匿名类的写法
Specificaiton<Customer> spec = new Specification<Customer>(){
// 实现toPredicate方法
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuild cd){
// 1.获取查询要比较的属性,返回值为path对象
Path<Obejct> custName = root.get("custName");
// 2.构造查询条件:第一个参数为要比较的属性(Path对象),第二个参数为属性值
Predicate predicate = cb.equal(custName,"zs");
return prediacate
}
}
Customer customer = customerDao.findOne(spec);
System.out.println(customer);
}
多条件:
Specificaiton<Customer> spec = new Specification<Customer>(){
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuild cd){
Path<Obejct> custName = root.get("custName");
Path<Obejct> custId = root.get("custId");
Predicate p1= cb.equal(custName,"zs");
Predicate p2= cb.equal(custId ,"1");
Predicate p3= cb.and(p1,p2);
return p3;
}
}
(2)findAll(Specification<T> spec)
模糊查询:
equal比较方式可以直接以path对象为参数,其他比较方式(gt、lt、ge、le、like)要根据path指定比较的参数类型,指定方法:path.as(类型的字节码)
Specificaiton<Customer> spec = new Specification<Customer>(){
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuild cd){
Path<Obejct> custName = root.get("custName");
Predicate predicate = cb.like(custName.as(String.class),"zs");
return predicate;
}
}
(3)findAll(Specification<T> spec, Pageable)
Pageable:可分页接口,实现类为PageRequest;PageRequest构造函数需要两个参数,当前页数、每页数量
Page:分页对象,分页查询的返回值。Page对象中包括查询的各种信息。
Specification spec = null;
Pageable pageable = new PageRequest(0,