type=page
status=published
title=Using the Criteria API and Metamodel API to Create Basic Typesafe Queries
next=persistence-string-queries.html
prev=persistence-criteria002.html
~~~~~~
= Using the Criteria API and Metamodel API to Create Basic Typesafe Queries


[[GJIVM]]

[[using-the-criteria-api-and-metamodel-api-to-create-basic-typesafe-queries]]
Using the Criteria API and Metamodel API to Create Basic Typesafe Queries
-------------------------------------------------------------------------

The basic semantics of a Criteria query consists of a `SELECT` clause, a
`FROM` clause, and an optional `WHERE` clause, similar to a JPQL query.
Criteria queries set these clauses by using Java programming language
objects, so the query can be created in a typesafe manner.

The following topics are addressed here:

* link:#GJIVS[Creating a Criteria Query]
* link:#GJIVQ[Query Roots]
* link:#GJIUV[Querying Relationships Using Joins]
* link:#GJIVE[Path Navigation in Criteria Queries]
* link:#GJIVI[Restricting Criteria Query Results]
* link:#GJIXE[Managing Criteria Query Results]
* link:#GJIVY[Executing Queries]

[[GJIVS]]

[[creating-a-criteria-query]]
Creating a Criteria Query
~~~~~~~~~~~~~~~~~~~~~~~~~

The `javax.persistence.criteria.CriteriaBuilder` interface is used to
construct

* Criteria queries
* Selections
* Expressions
* Predicates
* Ordering

To obtain an instance of the `CriteriaBuilder` interface, call the
`getCriteriaBuilder` method on either an `EntityManager` or an
`EntityManagerFactory` instance.

The following code shows how to obtain a `CriteriaBuilder` instance by
using the `EntityManager.getCriteriaBuilder` method:

[source,oac_no_warn]
----
EntityManager em = ...;
CriteriaBuilder cb = em.getCriteriaBuilder();
----

Criteria queries are constructed by obtaining an instance of the
following interface:

[source,oac_no_warn]
----
javax.persistence.criteria.CriteriaQuery
----

`CriteriaQuery` objects define a particular query that will navigate
over one or more entities. Obtain `CriteriaQuery` instances by calling
one of the `CriteriaBuilder.createQuery` methods. To create typesafe
queries, call the `CriteriaBuilder.createQuery` method as follows:

[source,oac_no_warn]
----
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
----

The `CriteriaQuery` object's type should be set to the expected result
type of the query. In the preceding code, the object's type is set to
`CriteriaQuery<Pet>` for a query that will find instances of the `Pet`
entity.

The following code snippet creates a `CriteriaQuery` object for a query
that returns a `String`:

[source,oac_no_warn]
----
CriteriaQuery<String> cq = cb.createQuery(String.class);
----

[[GJIVQ]]

[[query-roots]]
Query Roots
~~~~~~~~~~~

For a particular `CriteriaQuery` object, the root entity of the query,
from which all navigation originates, is called the query root. It is
similar to the `FROM` clause in a JPQL query.

Create the query root by calling the `from` method on the
`CriteriaQuery` instance. The argument to the `from` method is either
the entity class or an `EntityType<T>` instance for the entity.

The following code sets the query root to the `Pet` entity:

[source,oac_no_warn]
----
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
----

The following code sets the query root to the `Pet` class by using an
`EntityType<T>` instance:

[source,oac_no_warn]
----
EntityManager em = ...;
Metamodel m = em.getMetamodel();
EntityType<Pet> Pet_ = m.entity(Pet.class);
Root<Pet> pet = cq.from(Pet_);
----

Criteria queries may have more than one query root. This usually occurs
when the query navigates from several entities.

The following code has two `Root` instances:

[source,oac_no_warn]
----
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet1 = cq.from(Pet.class);
Root<Pet> pet2 = cq.from(Pet.class);
----

[[GJIUV]]

[[querying-relationships-using-joins]]
Querying Relationships Using Joins
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

For queries that navigate to related entity classes, the query must
define a join to the related entity by calling one of the `From.join`
methods on the query root object or another join object. The `join`
methods are similar to the `JOIN` keyword in JPQL.

The target of the join uses the Metamodel class of type `EntityType<T>`
to specify the persistent field or property of the joined entity.

The `join` methods return an object of type `Join<X, Y>`, where `X` is
the source entity and `Y` is the target of the join. In the following
code snippet, `Pet` is the source entity, `Owner` is the target, and
`Pet_` is a statically generated metamodel class:

[source,oac_no_warn]
----
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);

Root<Pet> pet = cq.from(Pet.class);
Join<Pet, Owner> owner = pet.join(Pet_.owners);
----

You can chain joins together to navigate to related entities of the
target entity without having to create a `Join<X, Y>` instance for each
join:

[source,oac_no_warn]
----
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);

Root<Pet> pet = cq.from(Pet.class);
Join<Owner, Address> address = pet.join(Pet_.owners).join(Owner_.addresses);
----

[[GJIVE]]

[[path-navigation-in-criteria-queries]]
Path Navigation in Criteria Queries
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

`Path` objects, which are used in the `SELECT` and `WHERE` clauses of a
Criteria query, can be query root entities, join entities, or other
`Path` objects. Use the `Path.get` method to navigate to attributes of
the entities of a query.

The argument to the `get` method is the corresponding attribute of the
entity's Metamodel class. The attribute can be either a single-valued
attribute, specified by `@SingularAttribute` in the Metamodel class, or
a collection-valued attribute, specified by one of
`@CollectionAttribute`, `@SetAttribute`, `@ListAttribute`, or
`@MapAttribute`.

The following query returns the names of all the pets in the data store.
The `get` method is called on the query root, `pet`, with the `name`
attribute of the `Pet` entity's Metamodel class, `Pet_`, as the
argument:

[source,oac_no_warn]
----
CriteriaQuery<String> cq = cb.createQuery(String.class);

Root<Pet> pet = cq.from(Pet.class);
cq.select(pet.get(Pet_.name));
----

[[GJIVI]]

[[restricting-criteria-query-results]]
Restricting Criteria Query Results
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Conditions that are set by calling the `CriteriaQuery.where` method can
restrict the results of a query on the `CriteriaQuery` object. Calling
the `where` method is analogous to setting the `WHERE` clause in a JPQL
query.

The `where` method evaluates instances of the `Expression` interface to
restrict the results according to the conditions of the expressions. To
create `Expression` instances, use methods defined in the `Expression`
and `CriteriaBuilder` interfaces.

[[GJIWN]]

[[the-expression-interface-methods]]
The Expression Interface Methods
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

An `Expression` object is used in a query's `SELECT`, `WHERE`, or
`HAVING` clause. link:#GJIWW[Table 43-1] shows conditional methods you
can use with `Expression` objects.

[[sthref180]][[GJIWW]]

*Table 43-1 Conditional Methods in the Expression Interface*

[width="50%",cols="15%,35%"]
|============================================================
|*Method* |*Description*
|`isNull` |Tests whether an expression is null
|`isNotNull` |Tests whether an expression is not null
|`in` |Tests whether an expression is within a list of values
|============================================================


The following query uses the `Expression.isNull` method to find all pets
where the `color` attribute is null:

[source,oac_no_warn]
----
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
cq.where(pet.get(Pet_.color).isNull());
----

The following query uses the `Expression.in` method to find all brown
and black pets:

[source,oac_no_warn]
----
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
cq.where(pet.get(Pet_.color).in("brown", "black"));
----

The `in` method can also check whether an attribute is a member of a
collection.

[[GJIXA]]

[[expression-methods-in-the-criteriabuilder-interface]]
Expression Methods in the CriteriaBuilder Interface
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The `CriteriaBuilder` interface defines additional methods for creating
expressions. These methods correspond to the arithmetic, string, date,
time, and case operators and functions of JPQL. link:#GJIXL[Table 43-2]
shows conditional methods you can use with `CriteriaBuilder` objects.

[[sthref181]][[GJIXL]]

*Table 43-2 Conditional Methods in the CriteriaBuilder Interface*

[width="60%",cols="15%,45%"]
|=======================================================================
|*Conditional Method* |*Description*
|`equal` |Tests whether two expressions are equal

|`notEqual` |Tests whether two expressions are not equal

|`gt` |Tests whether the first numeric expression is greater than the
second numeric expression

|`ge` |Tests whether the first numeric expression is greater than or
equal to the second numeric expression

|`lt` |Tests whether the first numeric expression is less than the
second numeric expression

|`le` |Tests whether the first numeric expression is less than or equal
to the second numeric expression

|`between` |Tests whether the first expression is between the second and
third expression in value

|`like` |Tests whether the expression matches a given pattern
|=======================================================================


The following code uses the `CriteriaBuilder.equal` method:

[source,oac_no_warn]
----
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
cq.where(cb.equal(pet.get(Pet_.name), "Fido"));
----

The following code uses the `CriteriaBuilder.gt` method:

[source,oac_no_warn]
----
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
Date someDate = new Date(...);
cq.where(cb.gt(pet.get(Pet_.birthday), date));
----

The following code uses the `CriteriaBuilder.between` method:

[source,oac_no_warn]
----
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
Date firstDate = new Date(...);
Date secondDate = new Date(...);
cq.where(cb.between(pet.get(Pet_.birthday), firstDate, secondDate));
----

The following code uses the `CriteriaBuilder.like` method:

[source,oac_no_warn]
----
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
cq.where(cb.like(pet.get(Pet_.name), "*do"));
----

To specify multiple conditional predicates, use the compound predicate
methods of the `CriteriaBuilder` interface, as shown in
link:#GJIWU[Table 43-3].

[[sthref182]][[GJIWU]]

*Table 43-3 Compound Predicate Methods in the CriteriaBuilder Interface*

[width="50%",cols="15%,35%"]
|=========================================================
|*Method* |*Description*
|`and` |A logical conjunction of two Boolean expressions
|`or` |A logical disjunction of two Boolean expressions
|`not` |A logical negation of the given Boolean expression
|=========================================================


The following code shows the use of compound predicates in queries:

[source,oac_no_warn]
----
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
cq.where(cb.equal(pet.get(Pet_.name), "Fido")
        .and(cb.equal(pet.get(Pet_.color), "brown")));
----

[[GJIXE]]

[[managing-criteria-query-results]]
Managing Criteria Query Results
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

For queries that return more than one result, it is often helpful to
organize those results. The `CriteriaQuery` interface defines the
following ordering and grouping methods:

* The `orderBy` method orders query results according to attributes of
an entity
* The `groupBy` method groups the results of a query together according
to attributes of an entity, and the `having` method restricts those
groups according to a condition

The following topics are addressed here:

* link:#GJIWO[Ordering Results]
* link:#GJIXG[Grouping Results]

[[GJIWO]]

[[ordering-results]]
Ordering Results
^^^^^^^^^^^^^^^^

To order the results of a query, call the `CriteriaQuery.orderBy`
method, passing in an `Order` object. To create an `Order` object, call
either the `CriteriaBuilder.asc` or the `CriteriaBuilder.desc` method.
The `asc` method is used to order the results by ascending value of the
passed expression parameter. The `desc` method is used to order the
results by descending value of the passed expression parameter. The
following query shows the use of the `desc` method:

[source,oac_no_warn]
----
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
cq.select(pet);
cq.orderBy(cb.desc(pet.get(Pet_.birthday)));
----

In this query, the results will be ordered by the pet's birthday from
highest to lowest. That is, pets born in December will appear before
pets born in May.

The following query shows the use of the `asc` method:

[source,oac_no_warn]
----
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
Join<Owner, Address> address = pet.join(Pet_.owners).join(Owner_.address);
cq.select(pet);
cq.orderBy(cb.asc(address.get(Address_.postalCode)));
----

In this query, the results will be ordered by the pet owner's postal
code from lowest to highest. That is, pets whose owner lives in the
10001 zip code will appear before pets whose owner lives in the 91000
zip code.

If more than one `Order` object is passed to `orderBy`, the precedence
is determined by the order in which they appear in the argument list of
`orderBy`. The first `Order` object has precedence.

The following code orders results by multiple criteria:

[source,oac_no_warn]
----
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
Join<Pet, Owner> owner = pet.join(Pet_.owners);
cq.select(pet);
cq.orderBy(cb.asc(owner.get(Owner_.lastName)), owner.get(Owner_.firstName)));
----

The results of this query will be ordered alphabetically by the pet
owner's last name, then first name.

[[GJIXG]]

[[grouping-results]]
Grouping Results
^^^^^^^^^^^^^^^^

The `CriteriaQuery.groupBy` method partitions the query results into
groups. To set these groups, pass an expression to `groupBy`:

[source,oac_no_warn]
----
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
cq.groupBy(pet.get(Pet_.color));
----

This query returns all `Pet` entities and groups the results by the
pet's color.

Use the `CriteriaQuery.having` method in conjunction with `groupBy` to
filter over the groups. The `having` method, which takes a conditional
expression as a parameter, restricts the query result according to the
conditional expression:

[source,oac_no_warn]
----
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
cq.groupBy(pet.get(Pet_.color));
cq.having(cb.in(pet.get(Pet_.color)).value("brown").value("blonde"));
----

In this example, the query groups the returned `Pet` entities by color,
as in the preceding example. However, the only returned groups will be
`Pet` entities where the `color` attribute is set to `brown` or
`blonde`. That is, no gray-colored pets will be returned in this query.

[[GJIVY]]

[[executing-queries]]
Executing Queries
~~~~~~~~~~~~~~~~~

To prepare a query for execution, create a `TypedQuery<T>` object with
the type of the query result, passing the `CriteriaQuery` object to
`EntityManager.createQuery`.

To execute a query, call either `getSingleResult` or `getResultList` on
the `TypedQuery<T>` object.

[[GJIUR]]

[[single-valued-query-results]]
Single-Valued Query Results
^^^^^^^^^^^^^^^^^^^^^^^^^^^

Use the `TypedQuery<T>.getSingleResult` method to execute queries that
return a single result:

[source,oac_no_warn]
----
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
...
TypedQuery<Pet> q = em.createQuery(cq);
Pet result = q.getSingleResult();
----

[[GJIVP]]

[[collection-valued-query-results]]
Collection-Valued Query Results
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Use the `TypedQuery<T>.getResultList` method to execute queries that
return a collection of objects:

[source,oac_no_warn]
----
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
...
TypedQuery<Pet> q = em.createQuery(cq);
List<Pet> results = q.getResultList();
----
