如何使用Spring Data Jpa帮助我们实现一些复杂的查询呢?
1. 接口分析
- 我们需要将我们自定义的接口继承一个叫做
JpaSpecificationExecutor
的接口,查看这个接口的源码你会发现,每个方法都有一个Specification类型的参数,其实这个参数就是我们可以进行复杂查询的关键。
public interface JpaSpecificationExecutor<T> {
T findOne(Specification<T> spec);
List<T> findAll(Specification<T> spec);
Page<T> findAll(Specification<T> spec, Pageable pageable);
List<T> findAll(Specification<T> spec, Sort sort);
long count(Specification<T> spec);
}
- 点进Specification,这也是一个接口,其中只有一个toPredicate方法,这个方法里面我们就可以自定义查询方式,三个参数的用法如下:
Root root:查询的根对象,可以从中获取查询的属性
CriteriaQuery<?> query:顶层查询对象,自定义查询的方式
CriteriaBuilder cb:查询的构造器,封装了很多查询条件
public interface Specification<T> {
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);
}
2.具体实现方式
场景一:查询以“张”开头的用户信息,并以id降序排序
@Test
public void testSpec1(){
Specification<User> spec = new Specification<User>() {
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//获取userName属性
Path<Object> userName = root.get("userName");
//传入获取的属性并指定类型
Predicate like = cb.like(userName.as(String.class), "张%");
return like;
}
};
List<User> users = userDao.findAll(spec);
System.out.println(users);
}
场景二:查询所在地为北京的用户,并分页显示
@Test
public void testSpec2(){
Specification<User> spec = new Specification<User>() {
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Path<Object> userAddress = root.get("userAddress");
//equal方法不需要传入参数类型
Predicate predicate = cb.equal(userAddress, "北京");
return predicate;
}
};
//创建一个分页对象
// 第一个参数代表第几页
// 第二个参数代表每页显示几条数据
Pageable pageable = new PageRequest(1, 2);
Page<User> page = userDao.findAll(spec, pageable);
System.out.println("当前页:"+page.getNumber());
System.out.println("当前页记录条数:"+page.getNumberOfElements());
System.out.println("总记录条数:"+page.getTotalElements());
System.out.println("总页数:"+page.getTotalPages());
System.out.println("当前页数据数据:"+page.getContent());
}
3.其他方法对应的sql含义
- 上面两个案例介绍了equal和like的使用,其他方法使用方式和这两个是一样的,大家可以根据上面的使用来测试
方法名称 | Sql对应关系 |
---|---|
equal | filed = value |
gt(greaterThan ) | filed > value |
lt(lessThan ) | filed < value |
ge(greaterThanOrEqualTo ) | filed >= value |
le( lessThanOrEqualTo) | filed <= value |
notEqule | filed != value |
like | filed like value |
notLike | filed not like value |