Spring Data JPA 中的分页和排序

1、概览

当我们数据库中的记录数量较多的时候,一般不会一次性检索出所有记录,通常会通过分页的方式展现。

此外,我们还经常需要在分页时根据某些条件对数据进行排序。

在本教程中,我们将学习如何使用 Spring Data JPA 轻松实现分页和排序。

2、创建实体

首先,假设我们有一个 Product 实体作为 domain 类:

@Entity 
public class Product {
  
    @Id
    private long id;
    private String name;
    private double price; 

    // 构造函数, getter 和 setter

}

我们的每个 Product 实例都有一个唯一的标识符: idnameprice

3、创建 Repository

要访问我们的 Product,我们需要一个 ProductRepository

public interface ProductRepository extends PagingAndSortingRepository<Product, Integer> {

    List<Product> findAllByPrice(double price, Pageable pageable);
}

通过让它继承 PagingAndSortingRepository,我们可以使用,用于分页和排序的 findAll(Pageable pageable)findAll(Sort sort) 方法。

相反,我们也可以选择继承 JpaRepository,因为它也继承了 PagingAndSortingRepository

一旦我们继承了 PagingAndSortingRepository,我们就可以添加自己的方法,使用 PageableSort 作为参数,就像上面代码中的 findAllByPrice 一样。

让我们看看如何使用新方法对 Product 进行分页检索。

4、分页

一旦我们的 repository 继承了 PagingAndSortingRepository ,那么我们只需要:

  1. 创建或获取 PageRequest 对象,它是 Pageable 接口的一个实现。
  2. PageRequest 对象作为参数传递给我们打算使用的 repository 方法。

我们可以通过如下方式指定“页数”和“每页记录数量”来创建 PageRequest 对象。

注意,页数从 0 开始

Pageable firstPageWithTwoElements = PageRequest.of(0, 2);

Pageable secondPageWithFiveElements = PageRequest.of(1, 5);

在 Spring MVC 中,我们还可以选择使用 Spring Data Web Support 在 controller 中获取 Pageable 实例。

有了 PageRequest 对象后,我们就可以在调用 repository 方法时将其传入:

Page<Product> allProducts = productRepository.findAll(firstPageWithTwoElements);

List<Product> allTenDollarProducts = 
  productRepository.findAllByPrice(10, secondPageWithFiveElements);

findAll(Pageable pageable) 方法默认返回一个 Page<T> 对象。

不过,我们也可以选择从任何返回分页数据的自定义方法中返回 Page<T>Slice<T>List<T>Page<T> 实例除了有 Product 列表外,还有总页数。为此,它会触发额外的 COUNT 查询。为了避免这种开销,我们可以直接返回一个 Slice<T>List<T>

Slice 不知道总记录数量,它只知道是否还有下一个 slice。

5、分页和排序

同样,如果只想对查询结果进行排序,我们只需向该方法传递一个 Sort 的实例即可:

Page<Product> allProductsSortedByName = productRepository.findAll(Sort.by("name"));

但是,如果我们想在分页的时候同时进行排序呢?

我们可以通过将排序的细节传递给 PageRequest 对象来实现:

Pageable sortedByName = 
  PageRequest.of(0, 3, Sort.by("name"));

Pageable sortedByPriceDesc = 
  PageRequest.of(0, 3, Sort.by("price").descending());

Pageable sortedByPriceDescNameAsc = 
  PageRequest.of(0, 5, Sort.by("price").descending().and(Sort.by("name")));

根据排序需求,我们可以在创建 PageRequest 实例时指定排序字段和排序方向。

像一般用法一样,我们可以将这个 Pageable 类型实例传递给 repository 的方法。

6、总结

在本文中,我们学习了如何在 Spring Data JPA 中对查询结果进行分页和排序。


参考:https://www.baeldung.com/spring-data-jpa-pagination-sorting