Start - Publikationen - Wissen - TOGAF - Impressum -

Paging mit setFirstResult und setMaxResults


Paging ist eine Optimierung, bei der über große ResultSets seitenweise navigiert wird. JPA unterstützt Paging, dabei können Queries mit den entsprechenden Angaben versehen werden:

Query query = em.createNamedQuery("Person.findByName");
query.setParameter("name", personName);
query.setFirstResult(10 * pagesize);
query.setMaxResults(50);
// das Resultat wird nur max. 50 Einträge haben und auf Seite 10 beginnen:
List<Person> persons = query.getResultList();
Die entsprechenden Paging-Informationen werden datenbankspezifisch an das Select angehängt und datenbankseitig ausgeführt.

Im Zusammenhang mit der Lösung des N+1 Problems für @OneToMany Relationen gibt es einen wichtigen Seiteneffekt bei der Arbeit mit JOIN FETCH zu berücksichtigen.

Angenommen man findet bei dem Beispiel mit der namedQuery 'Person.findByName.fetchOrgs' 10 Entitäten Person mit jeweils 10 Entitäten Organisation. Dann wird ein JOIN FETCH ein Ergebnis mit 100 Einträgen liefern, die 10 Personen jeweils redundant für die 10 Organisationen! Die Angaben zum Paging werden auf dieses Resultat bezogen und damit praktisch unsinnig. Die JPA Spezifikation stellt klar:

The effect of applying setMaxResults or setFirstResult to a query involving 
fetch joins over collections is undefined. (JPA "Enterprise JavaBeans 3.0, 
Final Release", Kapitel 3.6.1 Query Interface)
Hibernate liefert das richtige Ergebnis, indem es bei Join Fetches das Paging im Hauptspeicher der Anwendung durchführt. Auf das damit verbundene betriebliche Problem (dass ein Teil der Query von der JVM statt von der Datenbank ausgeführt wird) weist Hibernate hin:
WARNUNG: firstResult/maxResults specified with collection fetch; applying in memory!
Man vermeidet am besten die Kombination der Join Fetch Strategie mit Paging in produktiver Umgebung.
copyright © 2003-2021 | Dr. Christian Dürr | prozesse-und-systeme.de | all rights reserved