JPQL Criteria Queries

In JPA2 there is a query API referred to as "criteria". This is really an API allowing the construction of queries expression by expression, and optionally making it type safe so that if you refactor a field name then it is changed in the queries.

Creating a Criteria query

To use the JPA Criteria API, firstly you need to create a CriteriaQuery object for the candidate in question, and set the candidate, its alias, and the result to be of the candidate type

CriteriaBuilder cb = emf.getCriteriaBuilder();
CriteriaQuery<Person> crit = cb.createQuery(Person.class);
Root<Person> candidateRoot = crit.from(Person.class);
candidateRoot.alias("p");

crit.select(candidateRoot);

So what we have there equates to

SELECT p FROM mydomain.Person p

For a complete list of all methods available on CriteriaBuilder, refer to For a complete list of all methods available on CriteriaQuery, refer to



JPQL equivalent of the Criteria query

If you ever want to know what is the equivalent JPQL string-based query for your Criteria, just print out criteriaQuery.toString() . This is not part of the JPA spec, but something that we feel is very useful so is provided as a DataNucleus vendor extension. So, for example, the criteria query above would result in the following from crit.toString()

SELECT p FROM mydomain.Person p


Criteria API : Result clause

The basic Criteria query above is fine, but you may want to define a result other than the candidate. To do this we need to use the Criteria API.

Path nameField = candidateRoot.get("name");
crit.select(nameField);

which equates to

SELECT p.name


Criteria API : From clause joins

The basic Criteria query above is fine, but you may want to define some explicit joins. To do this we need to use the Criteria API.

Metamodel model = emf.getMetamodel();
ManagedType personType = model.type(Person.class);
Attribute addressAttr = personType.getAttribute("address");
Join addressJoin = candidateRoot.join((SingularAttribute)addressAttr);
addressJoin.alias("a");

which equates to

FROM mydomain.Person p JOIN p.address a


Criteria API : Filter

The basic Criteria query above is fine, but in the majority of cases we want to define a filter. To do this we need to use the Criteria API.

Path nameField = candidateRoot.get("name");
Predicate nameEquals = cb.equal(nameField, "First");
crit.where(nameEquals);

You can also invoke methods, so a slight variation on this clause would be

Predicate nameUpperEquals = cb.equal(cb.upper(nameField), "FIRST");

which equates to

WHERE (UPPER(p.name) = 'FIRST')


Criteria API : Ordering

The basic Criteria query above is fine, but in many cases we want to define ordering. To do this we need to use the Criteria API.

Path nameField = candidateRoot.get("name");
Order orderFirstName = cb.desc(nameField);
crit.orderBy(orderFirstName);

which equates to

ORDER BY p.name DESC


Criteria API : Parameters

Another common thing we would want to do is specify input parameters. To do this we need to use the Criteria API. Let's take an example of a filter with parameters.

Path nameField = candidateRoot.get("name");
ParameterExpression param1 = cb.parameter(String.class, "myParam1");
Predicate nameEquals = cb.equal(nameField, param1);
crit.where(nameEquals);

which equates to

WHERE (p.name = :myParam)

Don't forget to set the value of the parameters before executing the query!



Executing a Criteria query

Ok, so we've seen how to generate a Criteria query. So how can we execute it ? This is simple; convert it into a standard JPA query, set any parameter values and execute it.

Query query = em.createQuery(crit);
List<Person> results = query.getResultList();