JPQL and the Criteria API

Hibernate · lesson 11 of 32 · 4 min read

Query by entity and field names, then build the same query dynamically when you must.

Open this lesson in the learning hub

Key points

  • JPQL looks like SQL but names entities and fields: select b from Book b where b.author.name = :n.
  • Dotted paths become joins automatically. b.author.name is an inner join, so books with no author quietly drop out.
  • Always bind values with setParameter. Concatenating user input into a query is an injection hole here too.
  • For read-only screens select a DTO: select new com.app.BookView(b.title, b.pages). Much lighter than loading entities.
  • The Criteria API builds the same query as objects. Verbose, but the right tool when the filters depend on user input.
  • Generate the static metamodel (Book_.title) so a renamed field breaks the build instead of production.

Example

// JPQL - fixed shape, readable
List<Book> hits = em.createQuery(
        "select b from Book b where b.author.name = :name and b.pages > :min",
        Book.class)
    .setParameter("name", name)
    .setParameter("min", 300)
    .getResultList();

// Criteria - same query, assembled at runtime
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Book> query = cb.createQuery(Book.class);
Root<Book> book = query.from(Book.class);

List<Predicate> filters = new ArrayList<>();
if (name != null) {
    filters.add(cb.equal(book.get(Book_.author).get(Author_.name), name));
}
if (minPages != null) {
    filters.add(cb.gt(book.get(Book_.pages), minPages));
}
query.select(book).where(cb.and(filters.toArray(new Predicate[0])));

List<Book> dynamic = em.createQuery(query).getResultList();

JPQL for queries you know, Criteria for queries you assemble.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Hibernate course, and every lesson in it is listed on the Hibernate contents page.