分页的主要接口与类

PagingAndSortingRepository

  • 继承自 CrudRepository 接口,提供了排序以及分页查询能力,提供了两个方法
Iterable<T> findAll(Sort var1);
Page<T> findAll(Pageable var1);
  • 虽然 PagingAndSortingRepository 接口中只有 findAll 方法,但是我们依然可以使用 Repository 中的衍生查询,我们只要把 Pageable 放到最后一个参数即可
  • JpaRepository 接口继承了 PagingAndSortingRepository 接口,并封装了常用的 CRUD 方法,通常我们继承 JpaRepository 来进行操作

Sort

  • Sort 主要为了实现排序功能,内有枚举类指示排序方式
public static enum Direction {
ASC,
DESC;
//省略方法
}
  • Sort 的构造函数如下
//可以输入多个Sort.Order对象,在进行多个值排序时有用
public Sort(Sort.Order... orders)
//和上面的方法一样,无非把多个参数换成了一个List
public Sort(List<Sort.Order> orders)
//当排序方向固定时,使用这个比较方便,第一个参数是排序方向,第二个开始就是排序的字段,还有一个方法第二个参数是list,原理相同
public Sort(Sort.Direction direction, String... properties)
  • 建立一个 Sort
Sort sort = new Sort(Direction.DESC, "id");
  • Sort 中有一个内部类 Order,它用来定义排序方向和排序的列
Sort sort = new Sort(
new Sort.Order(Sort.Direction.ASC,"name"),
new Sort.Order(Sort.Direction.DESC,"address"));

Pageable

  • Pageable 是一个接口,提供了分页一组方法的声明,如第几页,每页多少条记录,排序信息等
int getPageNumber();

int getPageSize();

int getOffset();

Sort getSort();

Pageable next();

Pageable previousOrFirst();

Pageable first();

boolean hasPrevious();

PageRequest

  • 它是 Pageable 的实现类,它提供三个构造方法
//这个构造出来的分页对象不具备排序功能
public PageRequest(int page, int size) {
this(page, size, (Sort)null);
}
//Direction和properties用来做排序操作
public PageRequest(int page, int size, Direction direction, String... properties) {
this(page, size, new Sort(direction, properties));
}
//自定义一个排序的操作
public PageRequest(int page, int size, Sort sort) {
super(page, size);
this.sort = sort;
}
  • 第二个构造函数的 Direction 同样为 Sort 中的内部枚举,构建好 Sort、Pageable,就能实现 PagingAndSortingRepository 接口的排序和分页功能

分页与排序的使用

分页

声明一个 StudentPageRepository 接口继承自 PagingAndSortingRepository

public interface StudentPageRepository extends PagingAndSortingRepository<Student,Integer> {

    Page<Student> findByAge(int age, Pageable pageable);
}

创建分页对象 PageRequest,进行分页查询

//显示第1页每页显示3条
PageRequest pr = new PageRequest(1,3);
//根据年龄进行查询
Page<Student> stus = studentPageRepository.findByAge(22,pr);
  • 虽然 PagingAndSortingRepository 接口中只有 findAll 方法,但是我们依然可以使用 Repository 中的衍生查询,我们只要把 Pageable 放到最后一个参数即可

排序

声明一个 StudentPageRepository 接口继承自 PagingAndSortingRepository

public interface StudentPageRepository extends PagingAndSortingRepository<Student,Integer> {
Page<Student> findByAge(int age, Pageable pageable);
List<Student> findByAge(int age, Sort sort);
}

创建排序对象 Sort,进行查询排序

//设置排序方式为name降序
List<Student> stus = studentPageRepository.findByAge(22,new Sort(Sort.Direction.DESC,"name"));
//设置排序以name和address进行升序
stus = studentPageRepository.findByAge(22,new Sort(Sort.Direction.ASC,"name","address"));
//设置排序方式以name升序,以address降序
Sort sort = new Sort(new Sort.Order(Sort.Direction.ASC,"name"),new Sort.Order(Sort.Direction.DESC,"address"));
stus = studentPageRepository.findByAge(22,sort);

分页与排序

PageRequest 还提供了分页时进行排序的构造函数

public PageRequest(int page, int size, Direction direction, String... properties) {
this(page, size, new Sort(direction, properties));
} public PageRequest(int page, int size, Sort sort) {
super(page, size);
this.sort = sort;
}

JpaSpecificationExecutor

  • Spring Data Jpa 支持 Criteria 查询方式,使用这种方式需要继承 JpaSpecificationExecutor 接口,该接口提供了如下一些方法
T findOne(Specification<T> var1);
List<T> findAll(Specification<T> var1);
Page<T> findAll(Specification<T> var1, Pageable var2);
List<T> findAll(Specification<T> var1, Sort var2);
long count(Specification<T> var1);

通过实现 Specification 中的 toPredicate 方法来定义动态查询,通过 CriteriaBuilder 来创建查询条件

List<Student> stus = studentSpecificationRepository.findAll(new Specification<Student>() {
@Override
public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
//root.get("address")表示获取address这个字段名称,like表示执行like查询,%zt%表示值
Predicate p1 = criteriaBuilder.like(root.get("address"), "%zt%");
Predicate p2 = criteriaBuilder.greaterThan(root.get("id"),3);
//将两个查询条件联合起来之后返回Predicate对象
return criteriaBuilder.and(p1,p2);
}
});

可以定义多个 Specification,然后通过 Specifications 对象将其连接起来

//第一个Specification定义了两个or的组合
Specification<Student> s1 = new Specification<Student>() {
@Override
public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
Predicate p1 = criteriaBuilder.equal(root.get("id"),"2");
Predicate p2 = criteriaBuilder.equal(root.get("id"),"3");
return criteriaBuilder.or(p1,p2);
}
};
//第二个Specification定义了两个or的组合
Specification<Student> s2 = new Specification<Student>() {
@Override
public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
Predicate p1 = criteriaBuilder.like(root.get("address"),"zt%");
Predicate p2 = criteriaBuilder.like(root.get("name"),"foo%");
return criteriaBuilder.or(p1,p2);
}
};
//通过Specifications将两个Specification连接起来,第一个条件加where,第二个是and
List<Student> stus = studentSpecificationRepository.findAll(Specifications.where(s1).and(s2));

这个代码生成的 SQL 是

select * from t_student where (id=2 or id=3) and (address like 'zt%' and name like 'foo%')
  • toPredicate 中还有 CriteriaQuery 参数,这个对象提供了更多有用的查询,如分组之类的查询

Criteria 查询

API文档地址

  • CriteriaQuery 接口:该接口定义了顶级查询功能,它包含着查询到各个部分,如:select、from、where、group by、order by 等,CriteriaQuery 对象必须在实体类或嵌入式类型上才起作用
  • CriteriaBuilder:它是 CriteriaQuery 的工厂类,用于构建 JPA 安全查询,可通过 EntityManager.getCriteriaBuilder 而得
  • Root 接口:该接口继承了 From接口,From 接口继承了 Path 接口,该代表 Criteria 查询的根对象,定义了查询的实体类型,类似于 SQL 中的 FROM 子句,可有多个查询根
  • Predicate 接口:代表了简单或复杂的查询断言(语句),一个 Predicate 可认为由多个连接词构成

Criteria 查询 Demo

//创建CriteriaBuilder安全查询工厂
//CriteriaBuilder是一个工厂对象,安全查询的开始.用于构建JPA安全查询.
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
//创建CriteriaQuery安全查询主语句
//CriteriaQuery对象必须在实体类型或嵌入式类型上的Criteria 查询上起作用。
CriteriaQuery<Item> query = criteriaBuilder.createQuery(Item.class);
//Root 定义查询的From子句中能出现的类型
Root<Item> itemRoot = query.from(Item.class);
//Predicate 过滤条件 构建where字句可能的各种条件
//这里用List存放多种查询条件,实现动态查询
List<Predicate> predicatesList = new ArrayList<>();
//name模糊查询 ,like语句
if (name != null) {
predicatesList.add(
criteriaBuilder.and(
criteriaBuilder.like(
itemRoot.get(Item_.itemName), "%" + name + "%")));
}
// itemPrice 小于等于 <= 语句
if (price != null) {
predicatesList.add(
criteriaBuilder.and(
criteriaBuilder.le(
itemRoot.get(Item_.itemPrice), price)));
}
//itemStock 大于等于 >= 语句
if (stock != null) {
predicatesList.add(
criteriaBuilder.and(
criteriaBuilder.ge(
itemRoot.get(Item_.itemStock), stock)));
}
//where()拼接查询条件
query.where(predicatesList.toArray(new Predicate[predicatesList.size()]));
TypedQuery<Item> typedQuery = entityManager.createQuery(query);
List<Item> resultList = typedQuery.getResultList();
return resultList;

CriteriaBuilder 中各个方法的对应

equle : 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

若使用 Spring Data Jpa 则 Specification 代码如下

public Page<Item> findByConditions(String name, Integer price, Integer stock, Pageable page) {
Page<Item> page = itemRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
List<Predicate> predicatesList = new ArrayList<>();
//name模糊查询 ,like语句
if (name != null) {
predicatesList.add(
criteriaBuilder.and(
criteriaBuilder.like(
root.get(Item_.itemName), "%" + name + "%")));
}
// itemPrice 小于等于 <= 语句
if (price != null) {
predicatesList.add(
criteriaBuilder.and(
criteriaBuilder.le(
root.get(Item_.itemPrice), price)));
}
//itemStock 大于等于 >= 语句
if (stock != null) {
predicatesList.add(
criteriaBuilder.and(
criteriaBuilder.ge(
root.get(Item_.itemStock), stock)));
}
return criteriaBuilder.and(
predicatesList.toArray(new Predicate[predicatesList.size()]));
}, page);
return page;
}

作者:林塬
链接:https://www.jianshu.com/p/e7882c4f29b6
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

Spring Data Jpa:分页、Specification、Criteria的更多相关文章

  1. spring data jpa 分页查询

    https://www.cnblogs.com/hdwang/p/7843405.html spring data jpa 分页查询   法一(本地sql查询,注意表名啥的都用数据库中的名称,适用于特 ...

  2. spring data jpa封装specification实现简单风格的动态查询

    github:https://github.com/peterowang/spring-data-jpa-demo 单一实体的动态查询: @Servicepublic class AdvancedUs ...

  3. 使用Spring Data JPA的Specification构建数据库查询

    Spring Data JPA最为优秀的特性就是可以通过自定义方法名称生成查询来轻松创建查询SQL.Spring Data JPA提供了一个Repository编程模型,最简单的方式就是通过扩展Jpa ...

  4. Spring data Jpa 分页从1开始,查询方法兼容 Mybatis,分页参数兼容Jqgrid

    废话少说 有参数可以设置 在org.springframework.boot.autoconfigure.data.web.SpringDataWebProperties 中 /** * Whethe ...

  5. spring data jpa分页5种方法

    7.12.12 分页 本地sql查询 注意表名啥的都用数据库中的名称, 适用于特定数据库的查询 public interface UserRepository extends JpaRepositor ...

  6. spring data jpa分页

    controller层 @RequestMapping(value="/search") @ResponseBody public String search(HttpServle ...

  7. 解决neo4j @Transactional 与Spring data jpa @Transactional 冲突问题,@CreatedBy,@CreatedDate,@LastModifiedBy,@LastModifiedDate,以及解决@Version失效问题

    之前mybatis特别流行,所以前几个项目都是用@SelectProvider,@InsertProvider,@UpdateProvider,@DeleteProvider 加反射泛型封装了一些通用 ...

  8. Spring Data Jpa+SpringMVC+Jquery.pagination.js实现分页

    本博客介绍基于Spring Data这款orm框架加上Jquery.pagination插件实现的分页功能. 介绍一下Spring Data框架 spring Data : Spring 的一个子项目 ...

  9. Spring MVC和Spring Data JPA之按条件查询和分页(kkpaper分页组件)

    推荐视频:尚硅谷Spring Data JPA视频教程,一学就会,百度一下就有, 后台代码:在DAO层继承Spring Data JPA的PagingAndSortingRepository接口实现的 ...

随机推荐

  1. ts常用数据类型

    1.1 布尔值 let isTrue: boolean = false; console.log(isTrue); 1.2 数字 let age: number = 26; console.log(a ...

  2. jquery-uploadfile的使用(多文件异步上传)

    需求 在页面端可以在页面不刷新情况下上传多个有大小限制的word文件,并返回文件保存的路径,同时可以删除误上传的文件. 准备 下载该插件 该插件依赖jquery1.9.1版本(其它不清楚)*在jsp页 ...

  3. JavaScript初探 二 (了解数据)

    JavaScript初探 (二) JavaScript 事件 HTML事件 HTML事件是可以在浏览器或用户做的某些事情 HTML事件的例子: HTML网页完成加载 HTML输入字段被修改 HTML按 ...

  4. Apache2 在Linux环境下的安装

    安装Apache2: apt-get install apache2 启动Apache2服务: service apache2 start 在终端运行启动后,打开浏览器URL访问 http://loc ...

  5. 用BAPI_ACC_DOCUMENT_POST过账生成凭证

    根据前台需要输入参数,在bapi里面传值,不同业务所需参数不同. dome1: "bapi结构赋值     LOOP AT lt_item INTO lw_item.       wa_do ...

  6. SmobilerService 开发者日志(一):什么是 SmobilerService ,它为开发者带来了什么价值?

    初见 SmobilerService 你会发现几个版本,以及一些价格. 所以,"Smobiler 是要收费了吗?" 这是开发团队在幕后悄悄观察 Service 推广开始后,用户向运 ...

  7. 我认为现代IDE编辑器应该具有的几个特性和Visual studio 2010增强

    工作中要使用 VS 2010, 有好多年没有使用Visual studio 了, 试了一小会, 发现VS 2010 缺少不少现代IDE应有的特性, 我认为重要的是下面几个特性, VS2010 已经是1 ...

  8. Caused by: com.mysql.cj.exceptions.InvalidConnectionAttributeException: The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You must configure either the serv

    z 此问题为时区问题,在 JDBC 的连接 url 部分加上 useSSL=true&serverTimezone=UTC 即可.如图

  9. CodeForces - 1245D(思维+最小生成树)

    题意 https://vjudge.net/problem/CodeForces-1245D 已知一个平面上有 n 个城市,需要个 n 个城市均通上电 一个城市有电,必须在这个城市有发电站或者和一个有 ...

  10. django update_or_create

    update_or_create question.votes.update_or_create(user=request.user, defaults={"value": val ...