Spring Data JPA分页查询

本文介绍如何使用 SpringData JPA 进行分页查询并按特定字段排序。通过构造 PageRequest 对象来实现每页展示 10 条记录,并按照学生的分数进行倒序排列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用Spring Data JPA的朋友,在实际工作中经常需要用到分页查询。下面介绍一个简单的分页查询的例子:查询学生信息,每页10行数据,并按成绩排序。先看数据表:

 

实现:repo需要继承PagingAndSortingRepository,如下:

public interface StudentRepo extends CrudRepository<StudentEntity, String>,         JpaSpecificationExecutor,
        PagingAndSortingRepository<StudentEntity, String> {
}

需要用到PageRequest,我们来看一下PageRequest(为方便查看,本人去掉了部分内容,并增加了注释):

public class PageRequest extends AbstractPageRequest {

	private static final long serialVersionUID = -4541509938956089562L;

	private final Sort sort;

	//简单的,指定页码和每页行数
	public PageRequest(int page, int size) {
		this(page, size, null);
	}

	//指定页码、每页行数、排序
	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;
	}

	//下一页
	public Pageable next() {
		return new PageRequest(getPageNumber() + 1, getPageSize(), getSort());
	}

	//上一页
	public PageRequest previous() {
		return getPageNumber() == 0 ? this : new PageRequest(getPageNumber() - 1, getPageSize(), getSort());
	}

	//第一页
	public Pageable first() {
		return new PageRequest(0, getPageSize(), getSort());
	}
}

 我们发现,PageRequest提供了很多构造方法,根据实际情况灵活选择。下面看实现代码:

    public void queryStudentByPage() {
        //按分数倒序排列
        Sort sort = new Sort(Sort.Direction.DESC,"score");
        //构造PageRequest分页条件,第一页、每页10行、排序条件
        PageRequest pageRequest = new PageRequest(0,10, sort);
        Page<StudentEntity> page = studentRepo.findAll(pageRequest);
        List<StudentEntity> studentEntities = page.getContent();
        for (StudentEntity studentEntity : studentEntities) {
            System.out.println(studentEntity.toString());
        }
    }

查询结果如下:

Hibernate: 
    select
        studentent0_.id as id1_0_,
        studentent0_.address as address2_0_,
        studentent0_.birthday as birthday3_0_,
        studentent0_.name as name4_0_,
        studentent0_.school as school5_0_,
        studentent0_.score as score6_0_,
        studentent0_.tel as tel7_0_ 
    from
        t_student studentent0_ 
    order by
        studentent0_.score desc limit ?
Hibernate: 
    select
        count(studentent0_.id) as col_0_0_ 
    from
        t_student studentent0_

StudentEntity{id='6c09a952f5b9474fb56996db642e7bab', name='沙鸿飞', address='玉龙小区', tel='12314512312311', school='青大附中', birthday='2001-03-01', score=99}
StudentEntity{id='c46800036ea94caea07c1f2b90576c2f', name='赵继峰', address='菜市场', tel='12314512312311', school='大庆中学', birthday='2002-03-11', score=99}
StudentEntity{id='6b2bc83ff6ea4f7aa95986e3eeb1883f', name='赵六', address='玉龙小区', tel='12314512312311', school='青大附中', birthday='2001-03-01', score=98}
StudentEntity{id='76a5fad795aa4605b43daf9c5f4e8edd', name='张逸杰', address='菜市场', tel='12314512312311', school='胜利中学', birthday='2002-03-11', score=98}
StudentEntity{id='81fbeb9e7e8749e78c2495e169766274', name='吕春芳', address='柏景湾', tel='12314512312311', school='实验中学', birthday='2000-03-11', score=98}
StudentEntity{id='b6ef1f42e8a64367abc251af22246870', name='郎芬', address='菜市场', tel='12314512312311', school='西城中学', birthday='2001-03-11', score=98}
StudentEntity{id='bc56bad3fd4e4604abe8a1c4ee2c1f66', name='李海峰', address='菜市场', tel='12314512312311', school='明湖中学', birthday='2002-02-11', score=98}
StudentEntity{id='ded2215cfbb846d296aece2531bce6b8', name='赵九', address='岩石寨', tel='12314512312311', school='中山一小', birthday='2001-01-01', score=98}
StudentEntity{id='e838a9fbbd4240d5a0922d1112b2171d', name='钱十', address='南淮安', tel='12314512312311', school='西城中学', birthday='2001-03-31', score=98}
StudentEntity{id='babee95b37c04db38c0e74d923521ec5', name='钱十', address='南淮安', tel='12314512312311', school='山大附中', birthday='2001-03-11', score=89}

通过控制台打印出的sql我们发现里面通过limit限定返回从第几行到第几行的数据,另外发现不光查询了前10行的数据,还统计了总条数。那是因为返回的结果Page提供getTotalPages(获取总页数)、getTotalElements(获取总行数)等方法,需要在查询的时候获取总的数据行数。

 

### 如何使用 Spring Data JPA 实现分页查询 Spring Data JPA 提供了一种简单而强大的机制来实现数据的分页查询。以下是关于其工作原理和具体使用的详细介绍。 #### 使用 `Page` 和 `Pageable` 进行分页查询Spring Data JPA 中,可以通过定义 Repository 方法并传递 `Pageable` 对象来进行分页操作。`Pageable` 是一个接口,用于描述分页请求中的页面索引、页面大小和其他属性。返回结果通常是一个 `Page<T>` 类型的对象,它不仅包含了当前页的数据集合,还提供了有关总记录数、总页数以及其他元信息的方法[^1]。 下面展示了一个典型的例子: ```java import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; public interface UserRepository extends JpaRepository<User, Long> { // 定义支持分页的自定义查询方法 Page<User> findByStatus(String status, Pageable pageable); } ``` 在这个例子中,`findByStatus` 方法接受两个参数:一个是过滤条件(如状态),另一个是 `Pageable` 参数用来指定分页细节。调用此方法时可以传入具体的分页配置[^3]。 #### 创建 `Pageable` 实例 为了创建一个 `Pageable` 实例,最常用的方式就是利用 `PageRequest.of()` 静态工厂方法。该方法允许开发者设置起始页码(从零开始)、每页显示条目数目以及可选的排序规则[^4]。 示例如下: ```java import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; // 基础分页无排序 Pageable pageable = PageRequest.of(pageNumber, pageSize); // 添加升序排序 Pageable sortedByAsc = PageRequest.of(pageNumber, pageSize, Sort.by(Sort.Direction.ASC, "name")); // 复杂多字段排序 Pageable complexSort = PageRequest.of( pageNumber, pageSize, Sort.by(Sort.Order.asc("lastName"), Sort.Order.desc("firstName")) ); ``` 上述代码片段展示了三种不同类型的 `Pageable` 构造方式,分别对应于基本分页需求、单字段排序需求以及涉及多个字段复杂排序的需求。 #### 调用服务层完成最终查询逻辑 当 Repository 层已经准备好之后,在 Service 或 Controller 层就可以轻松地发起带有分页特性的数据库检索命令了。比如在一个 RESTful API 的场景里,可能像这样编写控制器代码: ```java @RestController @RequestMapping("/api/users") public class UserController { @Autowired private UserService userService; @GetMapping("/{pageNumber}/{pageSize}") public ResponseEntity<Page<User>> getUsers(@PathVariable int pageNumber, @PathVariable int pageSize){ Pageable paging = PageRequest.of(pageNumber - 1, pageSize); // 注意前端一般是从第一页即1开始计数 Page<User> pagedResult = userService.findAllUsers(paging); if (pagedResult.hasContent()) { return new ResponseEntity<>(pagedResult, HttpStatus.OK); } else{ return new ResponseEntity<>(HttpStatus.NO_CONTENT); } } } ``` 这里需要注意的是,由于 HTTP 请求路径变量通常是基于人类习惯设定的第一页为编号 “1”,而在内部计算过程中则需转换成以零为基础的位置表示形式。 --- ### 总结 通过以上介绍可以看出,借助 Spring Data JPA 可以非常方便快捷地构建出具备强大功能的应用程序组件,尤其是针对大数据量情况下的高效管理方案更是不可或缺的一部分[^2]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值