Paginierung im Winterschlaf

Winterschlaf-Paginierung

1. Überblick

Dieser Artikel ist eine schnelleintroduction to Pagination in Hibernate. Wir werden uns sowohl die Standard-HQL als auch dieScrollableResults-API und schließlich die Paginierung mit Hibernate-Kriterien ansehen.

Weitere Lektüre:

Bootstrapping Hibernate 5 mit Spring

Eine schnelle und praktische Anleitung zur Integration von Hibernate 5 in Spring.

Read more

Hibernate Inheritance Mapping

Ein praktischer Leitfaden zum Verständnis verschiedener Vererbungszuordnungsstrategien mit JPA / Hibernate.

Read more

Ruhezustand / JPA-SQL-Anweisungen von Spring Boot anzeigen

Erfahren Sie, wie Sie die Protokollierung der generierten SQL-Anweisungen in Ihrer Spring Boot-Anwendung konfigurieren können.

Read more

2. Paginierung mit HQL undsetFirstResult,setMaxResults API

Die einfachste und häufigste Methode zur Paginierung im Ruhezustand istusing HQL:

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

In diesem Beispiel wird eine grundlegendeFoo-Entität verwendet, die der JPA mit JQL-Implementierung sehr ähnlich ist. Der einzige Unterschied besteht in der Abfragesprache.

Wenn wirlogging for Hibernate aktivieren, wird die folgende SQL ausgeführt:

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

2.1. Die Gesamtzahl und die letzte Seite

Eine Paginierungslösung ist nicht vollständig, ohnethe total number of entities zu kennen:

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

Und schließlich können wir aus der Gesamtzahl und einer bestimmten Seitengrößethe last page berechnen:

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

An dieser Stelle können wir unsa complete example for pagination ansehen, wo wir die letzte Seite berechnen und dann abrufen:

@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. Paginierung mit Ruhezustand Verwenden von HQL und der ScrollableResults-API

Die Verwendung vonScrollableResulM. zur Implementierung der Paginierung kann zureduce database calls führen. Bei diesem Ansatz wird die Ergebnismenge beim Scrollen durch das Programm gestreamt, sodass die Abfrage nicht mehr wiederholt werden muss, um jede Seite zu füllen:

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;
}

Diese Methode ist nicht nur zeiteffizient (nur ein Datenbankaufruf), sondern ermöglicht dem Benutzer auch den Zugriff auf dietotal count of the result set without an additional query:

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

Beachten Sie andererseits, dass ein großes Fenster, obwohl das Scrollen sehr effizient ist, eine anständige Menge vonmemory beanspruchen kann.

4. Paginierung mit Ruhezustand mithilfe der Kriterien-API

Schauen wir uns zum Schlussa more flexible solution an - anhand von Kriterien:

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

Die Abfrage-API für Kriterien für den Ruhezustand macht es sehr einfach, auchget the total count zu verwenden - indem einProjection-Objekt verwendet wird:

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

Wie Sie sehen können, führt die Verwendung dieser API zu einem minimal ausführlicheren Code als bei einfachem HQL, jedoch zuthe API is fully type safe and a lot more flexible.

5. Fazit

Dieser Artikel ist eine kurze Einführung in die verschiedenen Möglichkeiten der Paginierung in Hibernate.

Die Implementierung dieses Spring JPA-Lernprogramms finden Sie inthe GitHub project - dies ist ein Eclipse-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein.