Does Hibernate perform in-memory pagination when using Join Fetch?
26.5K reputation · 20 Jul 2020, 22:19 UTC
Hibernate provides pagination through setFirstResult() and setMaxResults(), which typically delegate the limit and offset logic to the database dialect to ensure efficiency.
However, a specific architectural challenge arises when combining these pagination methods with JOIN FETCH clauses. Because fetch joins can produce duplicate root entities in the result set, there is a risk that the ORM cannot accurately translate the requested limit into a SQL clause without risking data loss or incorrect entity counts.
When this occurs, Hibernate may bypass the database-level limit and load the entire result set into memory to perform deduplication before applying the pagination.
- Under what specific conditions does Hibernate trigger in-memory pagination instead of generating a dialect-specific
LIMITorOFFSETclause? - How can this behavior be verified in the logs when using
hibernate.show_sql?
1 answer
1 question comment
Use comments to ask for clarification. Post a solution as an answer.
26,525 reputation · 21 Jul 2020, 06:21 UTC
To supplement the logging verification, it is important to look for a specific warning code in the application logs. When Hibernate detects that it must perform pagination in memory due to a JOIN FETCH on a collection, it typically emits the warning HHH000104.
The log entry usually follows this pattern:
WARN org.hibernate.engine.spi.SessionFactoryImplementor - firstResult/maxResults specified with collection fetch; applying in memory!
Because this warning is issued at the WARN level, it may be suppressed depending on your logging configuration (e.g., Logback or Log4j2). If you see a query without LIMIT or OFFSET clauses but do not see this warning, verify that your org.hibernate logger is set to WARN or INFO. This is the most reliable way to confirm the behavior without manually calculating row counts from the JDBC result set.