Hibernate Пагинация

Спящая пагинация

1. обзор

Эта статья представляет собой быстрыйintroduction to Pagination in Hibernate. Мы рассмотрим стандартный HQL, а также APIScrollableResults и, наконец, разбим на страницы с критериями гибернации.

Дальнейшее чтение:

Самозагрузка Hibernate 5 с весны

Краткое и практическое руководство по интеграции Hibernate 5 с Spring.

Read more

Hibernate Inheritance Mapping

Практическое руководство по пониманию различных стратегий отображения наследования с помощью JPA / Hibernate.

Read more

Показать Hibernate / JPA-операторы SQL из Spring Boot

Узнайте, как можно настроить ведение журнала сгенерированных операторов SQL в приложении Spring Boot.

Read more

2. Пагинация с HQL иsetFirstResult,setMaxResults API

Самый простой и распространенный способ разбивки на страницы в Hibernate -using HQL:

Session session = sessionFactory.openSession();
Query query = sess.createQuery("From Foo");
query.setFirstResult(0);
query.setMaxResults(10);
List fooList = fooList = query.list();

В этом примере используется базовая сущностьFoo, и он очень похож на JPA с реализацией JQL, с той лишь разницей, что язык запросов.

Если мы включимlogging for Hibernate, мы увидим выполнение следующего SQL:

Hibernate:
    select
        foo0_.id as id1_1_,
        foo0_.name as name2_1_
    from
        Foo foo0_ limit ?

2.1. Общее количество и последняя страница

Решение для разбивки на страницы не будет полным без знанияthe total number of entities:

String countQ = "Select count (f.id) from Foo f";
Query countQuery = session.createQuery(countQ);
Long countResults = (Long) countQuery.uniqueResult();

И, наконец, исходя из общего количества и заданного размера страницы, мы можем вычислитьthe last page:

int pageSize = 10;
int lastPageNumber = (int) (Math.ceil(countResults / pageSize));

На этом этапе мы можем посмотреть наa complete example for pagination, где мы вычисляем последнюю страницу, а затем получаем ее:

@Test
public void givenEntitiesExist_whenRetrievingLastPage_thenCorrectSize() {
    int pageSize = 10;
    String countQ = "Select count (f.id) from Foo f";
    Query countQuery = session.createQuery(countQ);
    Long countResults = (Long) countQuery.uniqueResult();
    int lastPageNumber = (int) (Math.ceil(countResults / pageSize));

    Query selectQuery = session.createQuery("From Foo");
    selectQuery.setFirstResult((lastPageNumber - 1) * pageSize);
    selectQuery.setMaxResults(pageSize);
    List lastPage = selectQuery.list();

    assertThat(lastPage, hasSize(lessThan(pageSize + 1)));
}

3. Разбиение на страницы в Hibernate с использованием HQL и ScrollableResults API

ИспользованиеScrollableResults для реализации разбивки на страницы может привести кreduce database calls. Этот подход обеспечивает потоковую передачу результирующего набора по мере его прокрутки, поэтому устраняется необходимость повторять запрос для заполнения каждой страницы:

String hql = "FROM Foo f order by f.name";
Query query = session.createQuery(hql);
int pageSize = 10;

ScrollableResults resultScroll = query.scroll(ScrollMode.FORWARD_ONLY);
resultScroll.first();
resultScroll.scroll(0);
List fooPage = Lists.newArrayList();
int i = 0;
while (pageSize > i++) {
    fooPage.add((Foo) resultScroll.get(0));
    if (!resultScroll.next())
        break;
}

Этот метод не только эффективен по времени (только один вызов базы данных), но и позволяет пользователю получить доступ кtotal count of the result set without an additional query:

resultScroll.last();
int totalResults = resultScroll.getRowNumber() + 1;

С другой стороны, имейте в виду, что, хотя прокрутка довольно эффективна, большое окно может занимать приличное количествоmemory.

4. Разбиение на страницы с помощью Hibernate с использованием API критериев

Наконец, давайте посмотрим наa more flexible solution - используя критерии:

Criteria criteria = session.createCriteria(Foo.class);
criteria.setFirstResult(0);
criteria.setMaxResults(pageSize);
List firstPage = criteria.list();

API запросов Hibernate Criteria упрощает такжеget the total count - с помощью объектаProjection:

Criteria criteriaCount = session.createCriteria(Foo.class);
criteriaCount.setProjection(Projections.rowCount());
Long count = (Long) criteriaCount.uniqueResult();

Как видите, использование этого API приведет к минимально более подробному коду, чем простой HQL, ноthe API is fully type safe and a lot more flexible.

5. Заключение

Эта статья представляет собой краткое введение в различные способы разбиения на страницы в Hibernate.

Реализацию этого учебника Spring JPA можно найти вthe GitHub project - это проект на основе Eclipse, поэтому его будет легко импортировать и запускать как есть.