Автор оригинала: Eugen Paraschiv.
1. Обзор
Эта статья представляет собой краткое введение в разбиение на страницы в спящем режиме . Мы рассмотрим стандартный HQL, а также ScrollableResults API и, наконец, разбиение на страницы с помощью критериев Hibernate.
Дальнейшее чтение:
Загрузка Hibernate 5 с пружиной
Отображение наследования в режиме гибернации
Показать инструкции Hibernate/JPA SQL из Spring Boot
2. Разбиение на страницы С помощью HQL и setFirstResult, setMaxResults API
Самый простой и распространенный способ разбиения на страницы в спящем режиме-это использование HQL :
Session session = sessionFactory.openSession(); Query query = sess.createQuery("From Foo"); query.setFirstResult(0); query.setMaxResults(10); ListfooList = fooList = query.list();
Этот пример использует базовую сущность Foo и очень похож на JPA с реализацией JQL – единственное различие заключается в языке запросов.
Если мы включим ведение журнала для Hibernate , мы увидим, что выполняется следующий SQL:
Hibernate: select foo0_.id as id1_1_, foo0_.name as name2_1_ from Foo foo0_ limit ?
2.1. Общее количество и Последняя страница
Решение для разбиения на страницы не является полным без знания общего количества сущностей :
String countQ = "Select count (f.id) from Foo f"; Query countQuery = session.createQuery(countQ); Long countResults = (Long) countQuery.uniqueResult();
И, наконец, из общего числа и заданного размера страницы мы можем вычислить последнюю страницу :
int pageSize = 10; int lastPageNumber = (int) (Math.ceil(countResults / pageSize));
На этом этапе мы можем посмотреть на полный пример разбиения на страницы , где мы вычисляем последнюю страницу, а затем извлекаем ее:
@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); ListlastPage = selectQuery.list(); assertThat(lastPage, hasSize(lessThan(pageSize + 1))); }
3. Разбиение на страницы С помощью Hibernate С использованием HQL и API ScrollableResults
Использование Прокручиваемого результата ts для реализации разбиения на страницы может привести к сокращению вызовов базы данных . Этот подход передает результирующий набор по мере его прокрутки программой, что устраняет необходимость повторять запрос для заполнения каждой страницы:
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); ListfooPage = Lists.newArrayList(); int i = 0; while (pageSize > i++) { fooPage.add((Foo) resultScroll.get(0)); if (!resultScroll.next()) break; }
Этот метод не только экономит время (только один вызов базы данных), но и позволяет пользователю получить доступ к общему количеству результирующего набора без дополнительного запроса :
resultScroll.last(); int totalResults = resultScroll.getRowNumber() + 1;
С другой стороны, имейте в виду, что, хотя прокрутка довольно эффективна, большое окно может занимать приличный объем памяти .
4. Разбиение На страницы С помощью Hibernate С использованием API Критериев
Наконец, давайте рассмотрим более гибкое решение – использование критериев:
Criteria criteria = session.createCriteria(Foo.class); criteria.setFirstResult(0); criteria.setMaxResults(pageSize); ListfirstPage = criteria.list();
Hibernate Criteria query API позволяет очень просто также получить общее количество – с помощью проекции объекта:
Criteria criteriaCount = session.createCriteria(Foo.class); criteriaCount.setProjection(Projections.rowCount()); Long count = (Long) criteriaCount.uniqueResult();
Как вы можете видеть, использование этого API приведет к минимально более подробному коду, чем обычный HQL, но API полностью безопасен для типов и намного более гибок .
5. Заключение
Эта статья представляет собой краткое введение в различные способы разбиения на страницы в режиме гибернации.
Реализацию этого весеннего руководства по JPA можно найти в проекте GitHub – это проект на основе Eclipse, поэтому его должно быть легко импортировать и запускать как есть.