Using the Criteria API to Create Queries

The Criteria API is used to define queries for entities and their persistent state by creating query-defining objects. Criteria queries are written using Java programming language APIs, are typesafe, and are portable. Such queries work regardless of the underlying data store.
The following topics are addressed here:


0.1 Overview of the Criteria and Metamodel APIs

Similar to JPQL, the Criteria API is based on the abstract schema of persistent entities, their relationships, and embedded objects. The Criteria API operates on this abstract schema to allow developers to find, modify, and delete persistent entities by invoking Java Persistence API entity operations. The Metamodel API works in concert with the Criteria API to model persistent entity classes for Criteria queries.
The Criteria API and JPQL are closely related and are designed to allow similar operations in their queries. Developers familiar with JPQL syntax will find equivalent object-level operations in the Criteria API.
The following simple Criteria query returns all instances of the Pet entity in the data source:
EntityManager em = ...;
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
cq.select(pet);
TypedQuery<Pet> q = em.createQuery(cq);
List<Pet> allPets = q.getResultList();
The equivalent JPQL query is
SELECT p
FROM Pet p

This query demonstrates the basic steps to create a Criteria query.
  1. Use an EntityManager instance to create a CriteriaBuilder object.
  2. Create a query object by creating an instance of the CriteriaQuery interface. This query object's attributes will be modified with the details of the query.
  3. Set the query root by calling the from method on the CriteriaQuery object.
  4. Specify what the type of the query result will be by calling the select method of the CriteriaQuery object.
  5. Prepare the query for execution by creating a TypedQuery<T> instance, specifying the type of the query result.
  6. Execute the query by calling the getResultList method on the TypedQuery<T> object. Because this query returns a collection of entities, the result is stored in a List.
The tasks associated with each step are discussed in detail in this chapter.
To create a CriteriaBuilder instance, call the getCriteriaBuilder method on the EntityManager instance:
CriteriaBuilder cb = em.getCriteriaBuilder();
Use the CriteriaBuilder instance to create a query object:
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
The query will return instances of the Pet entity. To create a typesafe query, specify the type of the query when you create the CriteriaQuery object.
Call the from method of the query object to set the FROM clause of the query and to specify the root of the query:
Root<Pet> pet = cq.from(Pet.class);
Call the select method of the query object, passing in the query root, to set the SELECT clause of the query:
cq.select(pet);
Now, use the query object to create a TypedQuery<T> object that can be executed against the data source. The modifications to the query object are captured to create a ready-to-execute query:
TypedQuery<Pet> q = em.createQuery(cq);
Execute this typed query object by calling its getResultList method, because this query will return multiple entity instances. The following statement stores the results in a List<Pet> collection-valued object:
List<Pet> allPets = q.getResultList();

0.2 Using the Metamodel API to Model Entity Classes

Use the Metamodel API to create a metamodel of the managed entities in a particular persistence unit. For each entity class in a particular package, a metamodel class is created with a trailing underscore and with attributes that correspond to the persistent fields or properties of the entity class.
The following entity class, com.example.Pet, has four persistent fields: idnamecolor, and owners:
package com.example;
...
@Entity
public class Pet {
    @Id
    protected Long id;
    protected String name;
    protected String color;
    @ManyToOne
    protected Set<Person> owners;
    ...
}
The corresponding Metamodel class is as follows:
package com.example;
...
@Static Metamodel(Pet.class)
public class Pet_ {

    public static volatile SingularAttribute<Pet, Long> id;
    public static volatile SingularAttribute<Pet, String> name;
    public static volatile SingularAttribute<Pet, String> color;
    public static volatile SetAttribute<Pet, Person> owners;
}
Criteria queries use the metamodel class and its attributes to refer to the managed entity classes and their persistent state and relationships.

0.2.1 Using Metamodel Classes

Metamodel classes that correspond to entity classes are of the following type:
javax.persistence.metamodel.EntityType<T>
Annotation processors typically generate metamodel classes either at development time or at runtime. Developers of applications that use Criteria queries may do either of the following:
  • Generate static metamodel classes by using the persistence provider's annotation processor
  • Obtain the metamodel class by doing one of the following:
    >>Call the getModel method on the query root object
    >>Obtain an instance of the Metamodel interface and then pass the entity type to the instance's entity method
    The following code snippet shows how to obtain the Pet entity's metamodel class by calling Root<T>.getModel:
    EntityManager em = ...;
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery cq = cb.createQuery(Pet.class);
    Root<Pet> pet = cq.from(Pet.class);
    EntityType<Pet> Pet_ = pet.getModel();
    
    The following code snippet shows how to obtain the Pet entity's metamodel class by first obtaining a metamodel instance by using EntityManager.getMetamodeland then calling entity on the metamodel instance:
    EntityManager em = ...;
    Metamodel m = em.getMetamodel();
    EntityType<Pet> Pet_ = m.entity(Pet.class);
    
    Note:
    The most common use case is to generate typesafe static metamodel classes at development time. Obtaining the metamodel classes dynamically, by calling Root<T>.getModel or EntityManager.getMetamodel and then the entity method, doesn't allow for type safety and doesn't allow the application to call persistent field or property names on the metamodel class.

    0.3 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.

    0.3.1 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 EntityManagerFactoryinstance.
    The following code shows how to obtain a CriteriaBuilder instance by using the EntityManager.getCriteriaBuilder method:
    EntityManager em = ...;
    CriteriaBuilder cb = em.getCriteriaBuilder();
    
    Criteria queries are constructed by obtaining an instance of the following interface:
    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:
    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:
    CriteriaQuery<String> cq = cb.createQuery(String.class);
    

    0.3.2 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:
    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:
    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:
    CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
    Root<Pet> pet1 = cq.from(Pet.class);
    Root<Pet> pet2 = cq.from(Pet.class);
    

    0.3.3 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:
    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:
    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);
    

    0.3.4 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.getmethod 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:
    CriteriaQuery<String> cq = cb.createQuery(String.class);
    
    Root<Pet> pet = cq.from(Pet.class);
    cq.select(pet.get(Pet_.name));
    

    0.3.5 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 Expressioninstances, use methods defined in the Expression and CriteriaBuilder interfaces.

    0.3.5.1 The Expression Interface Methods

    An Expression object is used in a query's SELECTWHERE, or HAVING clause. Table 40-1 shows conditional methods you can use with Expression objects.

    Table 40-1 Conditional Methods in the Expression Interface
    MethodDescription
    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:
    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:
    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.

    0.3.5.2 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. Table 40-2 shows conditional methods you can use with CriteriaBuilder objects.

    Table 40-2 Conditional Methods in the CriteriaBuilder Interface
    Conditional MethodDescription
    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:
    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:
    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:
    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:
    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 Table 40-3.

    Table 40-3 Compound Predicate Methods in the CriteriaBuilder Interface
    MethodDescription
    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:
    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")));
    

    0.3.6 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

    0.3.6.1 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 descmethod:
    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:
    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:
    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.

    0.3.6.2 Grouping Results
    The CriteriaQuery.groupBy method partitions the query results into groups. To set these groups, pass an expression to groupBy:
    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:
    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.

    0.3.7 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.

    0.3.7.1 Single-Valued Query Results
    Use the TypedQuery<T>.getSingleResult method to execute queries that return a single result:
    CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
    ...
    TypedQuery<Pet> q = em.createQuery(cq);
    Pet result = q.getSingleResult();
    

    0.3.7.2 Collection-Valued Query Results
    Use the TypedQuery<T>.getResultList method to execute queries that return a collection of objects:
    CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
    ...
    TypedQuery<Pet> q = em.createQuery(cq);
    List<Pet> results = q.getResultList();

    Creating and Using String-Based Criteria Queries

    This chapter describes how to create weakly typed string-based Criteria API queries.
    The following topics are addressed here:

    .1 Overview of String-Based Criteria API Queries

    String-based Criteria API queries ("string-based queries") are Java programming language queries that use strings rather than strongly typed metamodel objects to specify entity attributes when traversing a data hierarchy. String-based queries are constructed similarly to metamodel queries, can be static or dynamic, and can express the same kind of queries and operations as strongly typed metamodel queries.
    Strongly typed metamodel queries are the preferred method of constructing Criteria API queries.
    The main advantage of string-based queries over metamodel queries is the ability to construct Criteria queries at development time without the need to generate static metamodel classes or otherwise access dynamically generated metamodel classes.
    The main disadvantage to string-based queries is their lack of type safety; this problem may lead to runtime errors due to type mismatches that would be caught at development time if you used strongly typed metamodel queries.

    .2 Creating String-Based Queries

    To create a string-based query, specify the attribute names of entity classes directly as strings, instead of specifying the attributes of the metamodel class. For example, this query finds all Pet entities where the value of the name attribute is Fido:
    CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
    Root<Pet> pet = cq.from(Pet.class);
    cq.where(cb.equal(pet.get("name"), "Fido"));
    
    The name of the attribute is specified as a string. This query is the equivalent of the following metamodel query:
    CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
    Metamodel m = em.getMetamodel();
    EntityType<Pet> Pet_ = m.entity(Pet.class);
    Root<Pet> pet = cq.from(Pet.class);
    cq.where(cb.equal(pet.get(Pet_.name), "Fido"));
    
    Note:
    Type mismatch errors in string-based queries will not appear until the code is executed at runtime, unlike in the above metamodel query, where type mismatches will be caught at compile time.
    Joins are specified in the same way:
    CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
    Root<Pet> pet = cq.from(Pet.class);
    Join<Owner, Address> address = pet.join("owners").join("addresses");
    
    All the conditional expressions, method expressions, path navigation methods, and result restriction methods used in metamodel queries can also be used in string-based queries. In each case, the attributes are specified using strings. For example, here is a string-based query that uses the in expression:
    CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
    Root<Pet> pet = cq.from(Pet.class);
    cq.where(pet.get("color").in("brown", "black"));
    
    Here is a string-based query that orders the results in descending order by date:
    CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
    Root<Pet> pet = cq.from(Pet.class);
    cq.select(pet);
    cq.orderBy(cb.desc(pet.get("birthday")));

    .3 Executing String-Based Queries

    String-based queries are executed similarly to strongly typed Criteria queries. First create a javax.persistence.TypedQuery object by passing the criteria query object to the EntityManager.createQuery method, then call either getSingleResult or getResultList on the query object to execute the query:
    CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
    Root<Pet> pet = cq.from(Pet.class);
    cq.where(cb.equal(pet.get("name"), "Fido"));
    TypedQuery<Pet> q = em.createQuery(cq);
    List<Pet> results = q.getResultList();

    The JPA Criteria API provides an alternative way for defining JPA queries, which is mainly useful for building dynamic queries whose exact structure is only known at runtime.

    JPA Criteria API vs JPQL

    JPQL queries are defined as strings, similarly to SQL. JPA criteria queries, on the other hand, are defined by instantiation of Java objects that represent query elements.
    A major advantage of using the criteria API is that errors can be detected earlier, during compilation rather than at runtime. On the other hand, for many developers string based JPQL queries, which are very similar to SQL queries, are easier to use and understand.
    For simple static queries - string based JPQL queries (e.g. as named queries) may be preferred. For dynamic queries that are built at runtime - the criteria API may be preferred.
    For example, building a dynamic query based on fields that a user fills at runtime in a form that contains many optional fields - is expected to be cleaner when using the JPA criteria API, because it eliminates the need for building the query using many string concatenation operations.
    String based JPQL queries and JPA criteria based queries are equivalent in power and in efficiency. Therefore, choosing one method over the other is also a matter of personal preference. 

    First JPA Criteria Query

    The following query string represents a minimal JPQL query:
    SELECT c FROM Country c
    An equivalent query can be built using the JPA criteria API as follows:
      CriteriaBuilder cb = em.getCriteriaBuilder();
     
      CriteriaQuery<Country> q = cb.createQuery(Country.class);
      Root<Country> c = q.from(Country.class);
      q.select(c);
    The CriteriaBuilder interface serves as the main factory of criteria queries and criteria query elements. It can be obtained either by the EntityManagerFactory's getCriteriaBuildermethod or by the EntityManager's getCriteriaBuilder method (both methods are equivalent).
    In the example above a CriteriaQuery instance is created for representing the built query.
    Then a Root instance is created to define a range variable in the FROM clause. Finally, the range variable, c, is also used in the SELECT clause as the query result expression.
    CriteriaQuery instance is equivalent to a JPQL string and not to a TypedQuery instance.
    Therefore, running the query still requires a TypedQuery instance:
      TypedQuery<Country> query = em.createQuery(q);
      List<Country> results = query.getResultList();
    Using the criteria API introduces some extra work, at least for simple static queries, since the equivalent JPQL query could simply be executed as follows:
      TypedQuery<Country> query =
          em.createQuery("SELECT c FROM Country c", Country.class);
      List<Country> results = query.getResultList();
    Because eventually both types of queries are represented by a TypedQuery instance - query execution and query setting is similar, regardless of the way in which the query is built.

    Parameters in Criteria Queries

    The following query string represents a JPQL query with a parameter:
    SELECT c FROM Country c WHERE c.population > :p
    An equivalent query can be built using the JPA criteria API as follows:
      CriteriaBuilder cb = em.getCriteriaBuilder();
     
      CriteriaQuery<Country> q = cb.createQuery(Country.class);
      Root<Country> c = q.from(Country.class);
      ParameterExpression<Integer> p = cb.parameter(Integer.class);
      q.select(c).where(cb.gt(c.get("population"), p));
    The ParameterExpression instance, p, is created to represent the query parameter. The wheremethod sets the WHERE clause. As shown above, The CriteriaQuery interface supports method chaining. See the links in the next sections of this page for detailed explanations on how to set criteria query clauses and build criteria expressions.
    Running this query requires setting the parameter:
      TypedQuery<Country> query = em.createQuery(q);
      query.setParameter(p, 10000000);
      List<Country> results = query.getResultList();
    The setParameter method takes a Parameter (or a ParameterExpression) instance as the first argument instead of a name or a position (which are used with string based JPQL parameters).

    Criteria Query Structure

    Queries in JPA (as in SQL) are composed of clauses. Because JPQL queries and criteria queries use equivalent clauses - they are explained side by side in the Query Structure pages.
    Specific details about criteria query clauses are provided in the following page sections:
    The links above are direct links to the criteria query sections in pages that describe query structure in general, including in the context of string based JPQL queries.

    Criteria Query Expressions

    JPA query clauses are composed of expressions. Because JPQL queries and criteria queries use equivalent expressions - they are explained side by side in the Query Expressions pages.
    Specific details about criteria query expressions are provided in the following page sections:
    The links above are direct links to the criteria query sections in pages that describe expressions in general, including in the context of string based JPQL queries.