JPA Query Structure (JPQL / Criteria)
The syntax of the Jakarta Persistence Query Language (JPQL) is similar to SQL. This is a key advantage because SQL is a powerful query language, and many developers are already familiar with it.
The main difference between SQL and JPQL is that SQL operates on relational database tables, while JPQL operates on Java classes and objects. For example, a JPQL query can retrieve entities, unlike SQL, which returns only field values from database tables. This makes JPQL more object-oriented and easier to use in Java applications.
JPQL Query Structure
Like SQL, a JPQL SELECT query consists of up to six clauses in the following format:
SELECT ... FROM ... [WHERE ...] [GROUP BY ... [HAVING ...]] [ORDER BY ...]
The SELECT and FROM clauses are required in every query that retrieves data; update and delete queries have a slightly different structure. The other JPQL clauses--WHERE, GROUP BY, HAVING, and ORDER BY are optional.
The structure of JPQL DELETE and UPDATE queries is simpler:
DELETE FROM ... [WHERE ...] UPDATE ... SET ... [WHERE ...]
With a few exceptions, JPQL is case-insensitive. For example, JPQL keywords can be uppercase (e.g., SELECT) or lowercase (e.g., select). The exceptions, where JPQL is case-sensitive, include Java source elements such as the names of entity classes and persistent fields. String literals are also case-sensitive (e.g., "ORM" and "orm" are different values).
A Minimal JPQL Query
The following query retrieves all Country objects from the database:
SELECT c FROM Country AS c
This example demonstrates a minimal JPQL query because the SELECT and FROM clauses are mandatory.
The FROM clause declares one or more query variables, also known as identification variables. Query variables are similar to loop variables in programming languages. Each query variable represents an iteration over objects in the database. A query variable that is bound to an entity class is called a range variable. Range variables define an iteration over all the database objects of a bound entity class and its descendant classes. In the query above, c is a range variable that is bound to the Country entity class and defines an iteration over all Country objects in the database.
The SELECT clause defines the query results. The query above returns every Country object from the iteration of the c range variable, which in this case includes all Country objects in the database.
Organization of this Section
This section contains the following pages:
The following list links to detailed explanations of how to build clauses for Criteria API queries:
- Criteria SELECT (
selectjakarta.persistence.criteria.CriteriaQuery.select(Selection)Specify the item that is to be returned in the query result.,distinctjakarta.persistence.criteria.CriteriaQuery.distinct(boolean)Specify whether duplicate query results are eliminated.,multiselectjakarta.persistence.criteria.CriteriaQuery.multiselect(Selection...)Specify the selection items that are to be returned in the query result.,arrayjakarta.persistence.criteria.CriteriaBuilder.array(Selection...)Create an array-valued selection item.,tuplejakarta.persistence.criteria.CriteriaBuilder.tuple(Selection...)Create a tuple-valued selection item.,constructjakarta.persistence.criteria.CriteriaBuilder.construct(Class,Selection...)Create a selection item corresponding to a constructor.) - Criteria FROM (
fromjakarta.persistence.criteria.AbstractQuery.from(Class)Create and add a query root corresponding to the given entity, forming a cartesian product with any existing roots.,joinjakarta.persistence.criteria.From.join(String,JoinType)Create a join to the specified attribute using the given join type.,fetchjakarta.persistence.criteria.FetchParent.fetch(String)Create a fetch join to the specified attribute using an inner join.) - Criteria WHERE (
wherejakarta.persistence.criteria.CriteriaQuery.where(Predicate...)Modify the query to restrict the query result according to the conjunction of the specified restriction predicates.) - Criteria GROUP BY / HAVING (
groupByjakarta.persistence.criteria.CriteriaQuery.groupBy(Expression...)Specify the expressions that are used to form groups over the query results.,havingjakarta.persistence.criteria.CriteriaQuery.having(Expression)Specify a restriction over the groups of the query.,countjakarta.persistence.criteria.CriteriaBuilder.count(Expression)Create an aggregate expression applying the count operation.,sumjakarta.persistence.criteria.CriteriaBuilder.sum(Expression)Create an aggregate expression applying the sum operation.,avgjakarta.persistence.criteria.CriteriaBuilder.avg(Expression)Create an aggregate expression applying the avg operation.,minjakarta.persistence.criteria.CriteriaBuilder.min(Expression)Create an aggregate expression applying the numerical min operation.,maxjakarta.persistence.criteria.CriteriaBuilder.max(Expression)Create an aggregate expression applying the numerical max operation., ...) - Criteria ORDER BY (
orderByjakarta.persistence.criteria.CriteriaQuery.orderBy(Order...)Specify the ordering expressions that are used to order the query results.,Orderjakarta.persistence.criteria.OrderAn object that defines an ordering over the query results.,ascjakarta.persistence.criteria.CriteriaBuilder.asc(Expression)Create an ordering by the ascending value of the expression.,descjakarta.persistence.criteria.CriteriaBuilder.desc(Expression)Create an ordering by the descending value of the expression.)