Pagination and Sorting using Spring Data JPA – 使用Spring Data JPA进行分页和排序

最后修改: 2018年 12月 16日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Pagination is often helpful when we have a large dataset and we want to present it to the user in smaller chunks.

当我们有一个大的数据集,而我们想把它分成小块呈现给用户时,分页往往是有帮助的。

Also, we often need to sort that data by some criteria while paging.

另外,我们经常需要在分页时按一些标准对这些数据进行排序。

In this tutorial, we’ll learn how to easily paginate and sort using Spring Data JPA.

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

2. Initial Setup

2.初始设置

First, let’s say we have a Product entity as our domain class:

首先,假设我们有一个Product实体作为我们的领域类。

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

    // constructors, getters and setters 

}

Each of our Product instances has a unique identifier: id, its name and its price associated with it.

我们的每个产品实例都有一个独特的标识符。id,它的nameprice与之相关。

3. Creating a Repository

3.创建一个存储库

To access our Products, we’ll need a ProductRepository:

为了访问我们的Products,我们需要一个ProductRepository

public interface ProductRepository extends PagingAndSortingRepository<Product, Integer> {

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

By having it extend PagingAndSortingRepository, we get findAll(Pageable pageable) and findAll(Sort sort) methods for paging and sorting.

通过让它扩展PagingAndSortingRepository,我们得到findAll(Pageable pageable)findAll(Sort sort)方法来分页和排序。

Conversely, we could have chosen to extend JpaRepository instead, as it extends PagingAndSortingRepository too.

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

Once we extend PagingAndSortingRepository, we can add our own methods that take Pageable and Sort as parameters, like we did here with findAllByPrice.

一旦我们扩展了PagingAndSortingRepository我们可以添加自己的方法,将PageableSort作为参数,就像我们在这里做的findAllByPrice

Let’s take a look at how to paginate our Products using our new method.

让我们看看如何使用我们的新方法为我们的Products分页。

4. Pagination

4.分页

Once we have our repository extending from PagingAndSortingRepository, we just need to:

一旦我们有了从PagingAndSortingRepository扩展的版本库,我们只需要。

  1. Create or obtain a PageRequest object, which is an implementation of the Pageable interface
  2. Pass the PageRequest object as an argument to the repository method we intend to use

We can create a PageRequest object by passing in the requested page number and the page size.

我们可以通过传入请求的页码和页面大小来创建一个PageRequest对象。

Here the page count starts at zero:

这里页数从零开始:

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

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

In Spring MVC, we can also choose to obtain the Pageable instance in our controller using Spring Data Web Support.

在Spring MVC中,我们也可以选择使用Spring Data Web Support在控制器中获得Pageable实例。

Once we have our PageRequest object, we can pass it in while invoking our repository’s method:

一旦我们有了PageRequest对象,我们就可以在调用资源库的方法时把它传进去。

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

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

The findAll(Pageable pageable) method by default returns a Page<T> object.

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

However, we can choose to return either a Page<T>, a Slice<T>, or a List<T> from any of our custom methods returning paginated data.

然而,我们可以选择从任何返回分页数据的自定义方法中返回Page<T>、aSlice<T>、List<T>

A Page<T> instance, in addition to having the list of Products, also knows about the total number of available pages. It triggers an additional count query to achieve it. To avoid such an overhead cost, we can instead return a Slice<T> or a List<T>.

一个Page<T>实例,除了拥有Products的列表之外,还知道可用页面的总数。它触发了一个额外的计数查询来实现它。为了避免这样的开销成本,我们可以改为返回一个Slice<T>或一个List<T>

A Slice only knows whether the next slice is available or not.

一个只知道下一个片子是否可用。

5. Pagination and Sorting

5.分页和排序

Similarly, to just have our query results sorted, we can simply pass an instance of Sort to the method:

同样地,为了让我们的查询结果得到排序,我们可以简单地将一个Sort的实例传递给该方法。

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

However, what if we want to both sort and page our data?

然而,如果我们想同时对数据进行排序和分页呢?

We can do that by passing the sorting details into our PageRequest object itself:

我们可以通过将排序细节传入我们的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")));

Based on our sorting requirements, we can specify the sort fields and the sort direction while creating our PageRequest instance.

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

As usual, we can then pass this Pageable type instance to the repository’s method.

像往常一样,我们可以将这个Pageable类型的实例传递给资源库的方法。

6. Conclusion

6.结语

In this article, we learned how to paginate and sort our query results in Spring Data JPA.

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

As always, the complete code examples used in this article are available over on Github.

像往常一样,本文中使用的完整代码示例可在Github上获得