Jpa paging with numbers and next, previous

javafun picture javafun · Apr 13, 2012 · Viewed 21.7k times · Source

I apologize for asking this question if someone already asked it and for asking a perhaps dumb question but I am new to this and you are experts and I would love to learn from your expert advice and experience.

I want to add paging to an application displaying 200 records per page. The bottom of the page should have numbers. If there are 1050, the first page will display 100 and the bottom of the page will show numbers 1,2,3,4,5 & 6.

What is the general logic to accomplish this? I know that the database must select 200 every time and I must keep track of the first record.

  1. Is there a way to know how many records will be returned total so that I can know how many numbers to display on the bottom of the page? Does it require selecting a count() statement or something else?
  2. For the 1050 records, The numbers 1,2,3,4,5 & 6 will display and clicking each one requires a call to the server. Is there a way to know how many records will be returned in the next call to the server? Does it require selecting a count() statement or something else?

Answer

Perception picture Perception · Apr 13, 2012

You can use the JPA Criteria API to accomplish this. Assuming TypedQuery, you would use setFirstResult and setLastResult to limit the records returned from the database. Of course the values for these methods will be dependent on what page was requested, and how many records are getting displayed per page.

first = (page - 1) * page size;
last = (page * size) - 1;

Note: This assumes the first page is 1 (as opposed to zero).

To get a record count you execute a standard Criteria query. As an example:

final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
final CriteriaQuery<Long> countQuery = builder.createQuery(Long.class);
countQuery.select(builder.count(countQuery.from(MyEntity.class)));
final Long count = entityManager.createQuery(countQuery)
        .getSingleResult();

You can customize the above code to perform the count relative to another query as well. Finally, you need some way of communicating the total count back to the client. One way of doing this is wrapping the result set of your query in another object that contains an attribute for the count, or returns said object as a result of your DAO call. Or alternatively, you could store the count attribute in an object in your request scope.

public class ResultListWrapper<T> {
    private Long count;
    private Collection<T> results;

    // constructor, getters, setters
}