Question
Hibernate ORM and Java Application: Query Bounding and Pagination for Large Datasets
Kavi Indigo
0 reputation · 20 Mar 2024, 19:44 UTC
98K views
0 reputation · 20 Mar 2024, 19:44 UTC
The objective is to implement server‑side pagination in a Java application using Hibernate ORM so that large result sets are bounded and memory consumption remains acceptable.
JOIN FETCH together with setFirstResult and setMaxResults may trigger in‑memory pagination, defeating the purpose of server‑side limits.setFirstResult and setMaxResults into dialect‑specific SQL fragments (e.g., LIMIT/OFFSET for PostgreSQL/MySQL or FETCH NEXT for SQL Server), which can lead to different execution plans.JOIN FETCH is used, and how can this be avoided?setFirstResult and setMaxResults into dialect‑specific SQL, and can they be tuned for better performance?30775 reputation · 21 Mar 2024, 05:08 UTC
LIMIT/OFFSET for shallow pages (offset < 10,000). For offsets > 10k, switch to keyset pagination: WHERE id > :lastId ORDER BY id ASC LIMIT :pageSize. This avoids scanning the skipped rows.ORDER BY id OFFSET :offset ROWS FETCH NEXT :pageSize ROWS ONLY works well for moderate offsets. For very high offsets, emulate keyset with WHERE id > :lastId and TOP or use a windowed subquery.LIMIT/OFFSET and keyset. You must build the keyset query manually (e.g., via CriteriaBuilder or a native query).JOIN FETCH is present, because the SQL engine cannot safely apply LIMIT to a query that pulls whole collections.@BatchSize or EntityGraph).CROSS APPLY (SQL Server) in a native query and let the database handle pagination.Dialect classes generate the correct LIMIT/OFFSET or FETCH NEXT fragments. There is no property to switch strategies; the only tunable aspect is choosing the right Dialect (e.g., org.hibernate.dialect.PostgreSQL95Dialect vs PostgreSQLDialect).hibernate.show_sql=true
hibernate.format_sql=true
Check that the generated SQL contains LIMIT (PostgreSQL) or OFFSET … FETCH NEXT … (SQL Server).Dialect and override getLimitString(), but this requires careful maintenance across Hibernate upgrades.JOIN FETCH.CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Entity> q = cb.createQuery(Entity.class);
Root<Entity> root = q.from(Entity.class);
q.where(cb.greaterThan(root.get("id"), lastSeenId));
q.orderBy(cb.asc(root.get("id")));
TypedQuery<Entity> query = em.createQuery(q).setMaxResults(pageSize);
List<Entity> page = query.getResultList();
EXPLAIN ANALYZE in PostgreSQL or SET STATISTICS IO ON in SQL Server on the generated queries to confirm index usage.hibernate.generate_statistics=true) and check org.hibernate.stat.QueryExecutionStatistics for in‑memory pagination warnings.To give the most precise recommendation, could you share the exact Hibernate version (e.g., 5.6.x, 6.2.x) and the database version (PostgreSQL 14, SQL Server 2019)? These details influence which dialect features and JOIN FETCH behaviours are available.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.