Пагінація сплячого режиму

1. Огляд

Ця стаття - короткий вступ до Pagination in Hibernate . Ми розглянемо стандартний HQL, а також API ScrollableResults і, нарешті, пагінацію з критеріями Hibernate.

2. Пагінація за допомогою HQL та setFirstResult, API setMaxResults

Найпростіший і найпоширеніший спосіб зробити пагінацію в Hibernate - це використання 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 - єдина відмінність полягає в мові запитів.

Якщо ми ввімкнемо ведення журналу для 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); List lastPage = selectQuery.list(); assertThat(lastPage, hasSize(lessThan(pageSize + 1))); }

3. Пагінація за допомогою Hibernate за допомогою HQL та API ScrollableResults

Використання ScrollableResul 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); List fooPage = 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); List firstPage = criteria.list();

API запиту критеріїв сплячого режиму дозволяє дуже просто також отримати загальну кількість - за допомогою об’єкта Projection :

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

Як бачите, використання цього API призведе до мінімально детального коду, ніж звичайний HQL, але API повністю безпечний для набору типів і набагато гнучкіший .

5. Висновок

Ця стаття - короткий вступ до різних способів формування пагінації в сплячому режимі.

Здійснення цього весняного підручника з JPA можна знайти в проекті GitHub - це проект на основі Eclipse, тому його слід легко імпортувати та запускати як є.