Hibernate - HQL pagination

Most probably, if you create your own query with HQL, query builder methods cannot parse custom hql query and alter it. Therefore you should put your LIMIT ?, ? statement at the end of your HQL query and bind offset parameters then.


We can achieve the pagination by using Query and Criteria interface:

Pagination using Query Interface:

There are two methods of the Query interface for pagination.

1. Query setFirstResult(int startPosition): This method takes an integer that represents the first row in your result set, starting with row 0.

2. Query setMaxResults(int maxResult): This method tells Hibernate to retrieve a fixed number maxResults of objects. Using above two methods together, we can construct a paging component in our web or Swing application.

Example:

Query query = session.createQuery("FROM Employee");
query.setFirstResult(5);
query.setMaxResults(10);
List<Employee> list = query.list();
for(Employee emp: list) {            
   System.out.println(emp);
}

Pagination using Criteria Interface:

There are two methods of the Criteria interface for pagination.

1. Criteria setFirstResult(int firstResult):

Set the first result to be retrieved.

2. List item Criteria setMaxResults(int maxResults):

Set a limit upon the number of objects to be retrieved.

Example:

Criteria criteria = session.createCriteria(Employee.class);
criteria.setFirstResult(5);
criteria.setMaxResults(10);            
List<Employee> list = criteria.list();
for(Employee emp: list) {            
    System.out.println(emp);
}

Per the JPA 2.0 specification, section 3.8.6 Query Execution,

The effect of applying setMaxResults or setFirstResult to a query involving fetch joins over collections is undefined.

It varies from database to database, and in my experience, the result is Hibernate usually does the paging in memory instead of at the database query level.

What I've usually done is used a separate query to get the ids of the desired objects, and pass that into the query with the fetch join.


i'm using this solution:

/**
 * @param limitPerPage
 * @param page
 * @return
 */
public List<T> searchByPage(int limitPerPage, int page, String entity) {
    String sql = "SELECT t FROM " + entity + " t";
    Query query = em.createQuery(sql)
            .setFirstResult(calculateOffset(page, limitPerPage))
            .setMaxResults(limitPerPage);
    return query.getResultList();
}

/**
 * @param page
 * @return
 */
private int calculateOffset(int page, int limit) {
    return ((limit * page) - limit);
}

Welcome.