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, тому його слід легко імпортувати та запускати як є.