OutOfMemoryError during pagination with join fetch in Hibernate ORM
0 reputation · 09 Feb 2025, 22:55 UTC
0 reputation · 09 Feb 2025, 22:55 UTC
When utilizing setFirstResult() and setMaxResults() in Hibernate, the framework typically delegates pagination to the database using dialect-specific SQL clauses. However, a known behavior occurs when these methods are combined with join fetch on collection associations.
In environments with small datasets, such as local development, this configuration may appear functional. In production environments with large datasets, Hibernate may be unable to apply the pagination limit at the database level due to the Cartesian product created by the fetch join. This often results in the framework retrieving the entire result set into the JVM heap to perform pagination in memory.
This behavior is dependent on the Hibernate version and the specific database dialect used. Verification typically requires monitoring JVM heap usage and inspecting generated SQL to confirm the absence of LIMIT or OFFSET clauses.
join fetch is present?join fetch to avoid in-memory pagination while still reducing the N+1 select problem?32775 reputation · 10 Feb 2025, 06:09 UTC
When a query uses setFirstResult() and setMaxResults() together with a join fetch on a collection (to‑many) association, Hibernate cannot push the LIMIT/OFFSET clauses to the database.
Reason: the join creates a Cartesian product that would duplicate parent rows for each child, making offset/limit semantics ambiguous. Hibernate therefore falls back to in‑memory pagination: it fetches the full result set into the JVM heap and applies the firstResult/maxResults there.
LIMIT/OFFSET when a collection join fetch is present.WHERE parent.id IN (:ids) together with the desired join fetch. Because the ID list is already limited to the page, the second query returns exactly the needed rows.@BatchSize(size = N) (or set hibernate.default_batch_fetch_size).@Fetch(FetchMode.SUBSELECT).hibernate.show_sql=true) and run the original query; confirm the lack of LIMIT/OFFSET.Are you using Hibernate 5.x or 6.x? (If you are on a version older than 5.2, the @BatchSize annotation behaves slightly differently; let me know if you need a version‑specific note.)
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.