有时我们在查询某个实体的时候,给定的条件是不固定的,这时就需要动态构建相应的查询语句,在Spring Data JPA中可以通过JpaSpecificationExecutor接口查询。相比JPQL,其优势是类型安全,更加的面向对象。
JpaSpecificationExecutor接口的方法有:
Optional<T> findOne(@Nullable Specification<T> spec);
List<T> findAll(@Nullable Specification<T> spec);
Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable);
List<T> findAll(@Nullable Specification<T> spec, Sort sort);
long count(@Nullable Specification<T> spec);
boolean exists(Specification<T> spec);
核心参数是 Specification接口 可以采用内部类的方式或lambda表达式来创建。
自定义查询条件
1.实现Specification接口(提供泛型:查询的对象类型)
2.实现toPredicate方法构造查询条件)
3.需要借助方法参数中的两个参数(
root:获取需要查询的对象属性
CriteriaBuilder:构造查询条件的,内部封装了很多的查询条件(模糊匹配,精准匹配))
1. Optional<T> findOne(@Nullable Specification<T> spec); 条件查询
@SpringBootTest
public class Tes4 {
@Autowired
private CustomerDao dao;
@Test //one
public void show1(){
Specification<Customer> sp = (Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb)->{
Path<Object> custName = root.get("custName");
Predicate predicate = cb.equal(custName, "小王");
return predicate;
};
Optional<Customer> one = dao.findOne(sp);
System.out.println(one);
}
2.List<T> findAll(@Nullable Specification<T> spec);
@Test //多条件查询
public void show2(){
Specification<Customer> sp = ( root, query, cb)->{
Path<Object> custName = root.get("custName");
Path<Object> custAddress = root.get("custAddress");
Predicate p1 = cb.equal(custName, "小王");
Predicate p2 = cb.equal(custAddress, "吉祥村");
Predicate predicate = cb.or(p1, p2);
return predicate;
};
dao.findAll(sp).stream().forEach(System.out::println);
}
3.模糊查询
@Test //模糊
public void show3(){
Specification<Customer> sp = ( root, query, cb)->{
Path<Object> custName = root.get("custName");
Predicate predicate = cb.like(custName.as(String.class), "%老%");
return predicate;
};
dao.findAll(sp).stream().forEach(System.out::println);
}
4. List<T> findAll(@Nullable Specification<T> spec, Sort sort);
@Test //排序
public void show4(){
Specification<Customer> sp = ( root, query, cb)->{
Path<Object> custName = root.get("custName");
Predicate predicate = cb.like(custName.as(String.class), "%老%");
return predicate;
};
Sort sort = Sort.by(Sort.Direction.DESC, "custId");
dao.findAll(sp,sort).stream().forEach(System.out::println);
}
5. Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable);
@Test //分页
public void show5(){
Specification<Customer> sp = ( root, query, cb)->{
Path<Object> custName = root.get("custName");
Predicate predicate = cb.like(custName.as(String.class), "%老%");
return null;
};
PageRequest page = PageRequest.of(1, 2);
Page<Customer> list = dao.findAll(sp, page);
list.getContent().stream().forEach(System.out::println);//查询结果
System.out.println(list.getTotalElements()+"总数");
System.out.println(list.getTotalPages()+"总页数");
}