JPA Pagination – JPA分页

最后修改: 2014年 4月 8日


1. Overview


This article illustrates how to implement pagination in the Java Persistence API.

本文说明了如何在Java Persistence API中实现pagination

It explains how to do paging with basic JQL and with the more type-safe Criteria-based API’s, discussing the advantages and known issues of each implementation.


2. Pagination With JQL and the setFirstResult(), setMaxResults() API

2.用JQL和setFirstResult()setMaxResults() API进行分页

The simplest way to implement pagination is to use the Java Query Language – create a query and configure it via setMaxResults and setFirstResult:


Query query = entityManager.createQuery("From Foo");
int pageNumber = 1;
int pageSize = 10;
query.setFirstResult((pageNumber-1) * pageSize); 
List <Foo> fooList = query.getResultList();

The API is simple:


  • setFirstResult(int): Sets the offset position in the result set to start pagination
  • setMaxResults(int): Sets the maximum number of entities that should be included in the page

2.1. The Total Count and the Last Page


For a more complete pagination solution, we’ll also need to get the total result count:


Query queryTotal = entityManager.createQuery
    ("Select count( from Foo f");
long countResult = (long)queryTotal.getSingleResult();

Calculating the last page is also very useful:


int pageSize = 10;
int pageNumber = (int) ((countResult / pageSize) + 1);

Notice that this approach to getting the total count of the result set does require an additional query (for the count).


3. Pagination With JQL Using the Id’s of Entities


A simple alternative pagination strategy is to first retrieve the full ids and then – based on these – retrieve the full entities. This allows for better control of entity fetching – but it also means that it needs to load the entire table to retrieve the ids:


Query queryForIds = entityManager.createQuery(
  "Select from Foo f order by f.lastName");
List<Integer> fooIds = queryForIds.getResultList();
Query query = entityManager.createQuery(
  "Select f from Foo e where in :ids");
query.setParameter("ids", fooIds.subList(0,10));
List<Foo> fooList = query.getResultList();

Finally, also note that it requires 2 distinct queries to retrieve the full results.


4. Pagination With JPA Using Criteria API


Next, let’s look at how we can leverage the JPA Criteria API to implement pagination:

接下来,让我们看看我们如何利用JPA Criteria API来实现分页。

int pageSize = 10;
CriteriaBuilder criteriaBuilder = entityManager
CriteriaQuery<Foo> criteriaQuery = criteriaBuilder
Root<Foo> from = criteriaQuery.from(Foo.class);
CriteriaQuery<Foo> select =;
TypedQuery<Foo> typedQuery = entityManager.createQuery(select);
List<Foo> fooList = typedQuery.getResultList();

This is useful when the aim is to create dynamic, failure-safe queries. In contrast to “hard-coded”, “string-based” JQL or HQL queries, JPA Criteria reduces run-time failures because the compiler dynamically checks for query errors.

当目的是创建动态的、无故障的查询时,这很有用。与 “硬编码”、”基于字符串 “的JQL或HQL查询相比,JPA Criteria减少了运行时的故障,因为编译器会动态地检查查询错误。

With JPA Criteria getting the total number of entities in simple enough:


CriteriaQuery<Long> countQuery = criteriaBuilder
Long count = entityManager.createQuery(countQuery)

The end result is a full pagination solution, using the JPA Criteria API:

最终的结果是一个完整的分页解决方案,使用JPA Criteria API。

int pageNumber = 1;
int pageSize = 10;
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();

CriteriaQuery<Long> countQuery = criteriaBuilder
Long count = entityManager.createQuery(countQuery)

CriteriaQuery<Foo> criteriaQuery = criteriaBuilder
Root<Foo> from = criteriaQuery.from(Foo.class);
CriteriaQuery<Foo> select =;

TypedQuery<Foo> typedQuery = entityManager.createQuery(select);
while (pageNumber < count.intValue()) {
    typedQuery.setFirstResult(pageNumber - 1);
    System.out.println("Current page: " + typedQuery.getResultList());
    pageNumber += pageSize;

5. Conclusion


This article has explored the basic pagination options available in JPA.


Some have drawbacks – mainly related to query performance, but these are usually offset by improved control and overall flexibility.


The implementation of this Spring JPA Tutorial can be found in the GitHub project – this is a Maven-based project, so it should be easy to import and run as it is.

这个Spring JPA教程的实现可以在GitHub项目中找到 – 这是一个基于Maven的项目,因此应该很容易导入并按原样运行。