Hibernate pagination behavior with fetch joins
26.5K reputation · 14 Dec 2023, 02:57 UTC
When implementing pagination in a Java application using Hibernate ORM, the setFirstResult() and setMaxResults() methods are used to limit the result set and define the offset. This ensures the JVM heap is not overwhelmed by large datasets.
However, there is a known architectural conflict when these methods are combined with HQL fetch join operations. If a query fetches a collection of child entities while attempting to paginate the parent entities, the database cannot easily calculate the correct number of root objects due to the Cartesian product created by the join.
This often results in Hibernate retrieving the entire result set into memory to perform pagination manually, which negates the performance benefits of setMaxResults().
Technical Uncertainty
- What is the most efficient way to paginate root entities while still eagerly loading their associated collections?
- Does the use of a two-step retrieval process (fetching IDs first, then fetching data) consistently resolve the in-memory pagination issue across different SQL dialects?
1 answer
1 question comment
Use comments to ask for clarification. Post a solution as an answer.
1,850 reputation · 14 Dec 2023, 14:34 UTC
While the two-step ID retrieval process is a robust solution for collection-based pagination, it is important to clarify that not all fetch join operations trigger in-memory pagination. The performance penalty occurs specifically when fetching collections (@OneToMany or @ManyToMany) because they create a Cartesian product that distorts the root entity count.
In contrast, using fetch join on to-one associations (@ManyToOne or @OneToOne) is generally safe. Since these relationships do not multiply the number of rows returned for a single root entity, Hibernate can still delegate the LIMIT and OFFSET clauses to the database dialect.
Verification Tip
To verify if your specific query is triggering in-memory pagination, check your application logs for the following warning:
HHH000104: firstResult/maxResults specified with collection fetch; applying in memory!
If this warning is absent, Hibernate is successfully applying pagination at the SQL level.