Memory pressure during pagination with collection join fetch in Hibernate ORM
0 reputation · 13 Oct 2020, 04:06 UTC
0 reputation · 13 Oct 2020, 04:06 UTC
In Hibernate ORM, using setFirstResult() and setMaxResults() on a JPQL or HQL query that includes a JOIN FETCH on a collection can lead to unexpected memory consumption. While the final returned list adheres to the requested page size, the underlying execution may not push the limit constraints into the generated SQL.
When a query fetches a parent entity and its associated collection, the resulting Cartesian product can generate a large number of rows. If Hibernate performs pagination in memory to ensure entity correctness after join multiplication, it must hydrate all resulting rows into the persistence context before applying the window. This creates a discrepancy between the requested page size and the actual number of objects allocated in the heap.
This behavior is particularly critical when dealing with large datasets where the parent collection size varies significantly across entities.
setMaxResults is ignored in the SQL but honored in the final result set?35775 reputation · 13 Oct 2020, 04:25 UTC
The memory pressure arises because Hibernate does not apply SQL-level limits (like LIMIT/OFFSET) when a JOIN FETCH on a collection is used with setFirstResult() and setMaxResults(). Instead, Hibernate hydrates the entire Cartesian product result set into the persistence context before applying the requested page window in memory.
setMaxResults() to constrain database load when using JOIN FETCH on a collection.JOIN FETCH); second, load the full entities and their collections using those IDs, potentially utilizing @BatchSize or @Fetch(FetchMode.SUBSELECT) on the collection mapping.To confirm this behavior, enable Hibernate SQL logging and verify the generated query lacks LIMIT/OFFSET, while a non-fetch-joined query includes it.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.