skip to content

HQL, JPQL & Criteria API

Hibernate's query toolbox: entity-oriented JPQL/HQL, type-safe Criteria for dynamic filters, native SQL escape hatches, DTO projections, pagination, and bulk statements. Interviewers probe here to see whether you can pick the right query tool and know which ones bypass the persistence context.

part ofHibernateoverview, primer and where to startread it →
on this pageshow

explore

questions

page 2 of 2

You lead a team on a JPA codebase where raw SQL through createNativeQuery is spreading. How do you decide which queries legitimately belong in raw SQL, and what do you put in place so those queries do not become a liability?

level: principalimportance: should knowfreq 28%

basics

~20 s

Allow raw SQL where the object query language genuinely cannot express it or produces measurably wrong SQL — window functions, recursive CTEs, vendor features, set-based bulk work. Contain it: name and centralise the queries, map results into DTOs, and cover each one with integration tests on the real engine, since none of it is validated at startup.

open as a page

How do you join two entities in a JPQL or HQL query when there is no mapped association between them?

level: middleimportance: nice to knowfreq 34%

basics

~20 s

Use an entity join with an explicit condition: FROM A a JOIN B b ON b.code = a.code. Hibernate has supported this since 5.1 and Jakarta Persistence 3.2 standardises it. The older portable fallback is listing both entities in FROM and joining in WHERE.

open as a page

HQL supports statements of the form 'insert into CustomerArchive (id, name) select ... from Customer c where ...'. What does such a statement do, what restrictions apply around identifiers and version columns, and when is it worth using instead of reading rows into memory?

level: seniorimportance: nice to knowfreq 20%

basics

~20 s

It performs a server-side INSERT ... SELECT: rows are copied entity-to-entity without leaving the database. No entities are instantiated, so no callbacks or cascades run. Identifiers must be selected or come from a generator usable inside the statement, not an identity column.

open as a page

Does a JPQL bulk UPDATE touch an entity's version column, and what does the HQL keyword in 'update versioned Customer c set c.status = :s' actually do?

level: seniorimportance: nice to knowfreq 26%

basics

~20 s

A plain bulk UPDATE leaves the version column unchanged, so other sessions holding the row keep believing their copy is current. HQL's 'update versioned' makes Hibernate increment the version column as part of the same statement.

open as a page

Using CriteriaBuilder, how do you express an inner join to a related entity and a correlated subquery, and what is the difference between calling join() and fetch() on a Root?

level: seniorimportance: nice to knowfreq 30%

basics

~20 s

root.join("customer", JoinType.INNER) returns a Join you can navigate and filter on. root.fetch("lines") returns a Fetch — it loads the association eagerly but is not usable in WHERE, so you cannot filter through it (people cast Fetch to Join to reuse it). Subqueries: cq.subquery(Long.class), its own from(), correlate() for the outer root, then cb.exists / cb.in.

open as a page

Hibernate's HQL is a superset of the Jakarta Persistence query language — what concrete capabilities does HQL add beyond the specification, and what do you give up by using them?

level: seniorimportance: nice to knowfreq 32%

basics

~20 s

HQL adds an explicit limit/offset clause, set operations, window functions, common table expressions, subqueries in FROM, ad-hoc entity joins, a much larger function library, and shortcuts like omitting SELECT. The cost is provider lock-in: those queries only run on Hibernate.

open as a page

Beyond holding the query text, a JPA @NamedQuery declaration can carry query hints and a lock mode. What can you attach there, and why would you prefer attaching it to the declaration over setting it at each call site?

level: seniorimportance: nice to knowfreq 26%

basics

~20 s

@NamedQuery accepts a lockMode plus @QueryHint entries such as timeout, JDBC fetch size, read-only mode, query-cache participation and a SQL comment. Attaching them to the declaration makes the policy travel with the query, so no call site can forget it and every caller gets identical behaviour.

open as a page

You own a JPQL-backed listing over a table of tens of millions of rows, where each listed row also shows a few of its child records. How do you decide the pagination strategy, and what guardrails do you put on it?

level: principalimportance: nice to knowfreq 30%

basics

~20 s

Decide from the access pattern: numbered pages and shallow browsing tolerate offsets; feeds, exports and deep scrolling need keyset cursors. Never fetch-join collections into a paged query — project DTOs or batch-load children. Cap page size and depth server-side.

open as a page

showing 31–38 of 38