Paths and Types in JPQL and Criteria API

Instances of user defined persistable classes (entity classes, mapped super classes and embeddable classes) are represented in JPQL by the following types of expressions:

  • Variables - FROM identification variables and SELECT result variables.
  • Parameters - when instances of these classes are assigned as arguments.
  • Path expressions that navigate from one object to another.

Instances of user defined persistable classes can participate in direct comparison using the = and <> operators. But more often they are used in JPQL path expressions that navigate to values of simple types (number, boolean, string, date).

Simple type values are more useful in queries. They have special operators and functions (e.g. for strings and for numbers), they can be compared by all six comparison operators, and they can be used in ordering.

A path expression always starts with an instance of a user defined class (represented by a variable, parameter or prefix path expression) and uses the dot (.) operator to navigate through persistent fields to other objects and values.

For example - c.capital, where c represents a Country entity object uses the capital persistent field in the Country class to navigate to the associated Capital entity object.

Path expression whose type is a persistable user class can be extended further by reusing the dot (.) operator. For example, c.capital.name is a nested path expression that continues from the Capital entity object to its name field. A path expression can be extended further only if its type is also a user defined persistable class. The dot (.) operator cannot be applied to collections, maps and values of simple types (number, boolean, string, date).

For a path expression to be valid the user defined persistable class must contain a persistent field (or property) with a matching name. The path expression, however, is valid even if the persistent field is declared as private (which is usually the case).

The following query retrieves country names with their capital city names:
SELECT c.name, c.capital.name FROM Country c

The c identification variable is used to iterate over all the Country objects in the database.

For a country with no capital city, such as Nauru, c.capital is evaluated to NULL and c.capital.name is an attempt to navigate from a NULL value. In Java, a NullPointerException is thrown on any attempt to access a field or a method via a null reference. In JPQL, the current FROM variable (or FROM tuple when there are multiple variables) is simply skipped. It might be easier to understand exactly how this works by considering the equivalent JOIN query.

Entity Type Expressions

The TYPE operator (which is new in JPA 2) returns the type of a specified argument, similarly to java.lang.Object's getClass method in Java.

The following query returns the number of all the entity objects in the database, excluding Country entity objects:

SELECT COUNT(e) FROM Object e WHERE TYPE(e) <> Country

Binding an identification variable (e) to the Object class is an extension of ObjectDB that can be used to iterate over all the entity objects in the database. The Country literal represents the Country entity class. The TYPE operator returns the actual type of the iterated e. Only objects whose type is not Country are passed to the SELECT. The SELECT clause counts all these objects (this is an aggregate query with no GROUP BY - all the objects are considered as one group, and COUNT calculates its size).

Criteria Query Paths and Types

Paths and navigations are represented in the JPA Criteria API by the Pathjavax.persistence.criteria.Path - JPA InterfaceRepresents a simple or compound attribute path from a bound type or collection, and is a "primitive" expression. interface and by its subinterfaces (Fromjavax.persistence.criteria.From - JPA InterfaceRepresents a bound type, usually an entity that appears in the from clause, but may also be an embeddable belonging to an entity in the from clause., Rootjavax.persistence.criteria.Root - JPA InterfaceA root type in the from clause., Joinjavax.persistence.criteria.Join - JPA InterfaceA join to an entity, embeddable, or basic type. and Join's descendants).

Path Expressions

The Rootjavax.persistence.criteria.Root - JPA InterfaceA root type in the from clause. and Joinjavax.persistence.criteria.Join - JPA InterfaceA join to an entity, embeddable, or basic type. interfaces (which are subinterfaces of Fromjavax.persistence.criteria.From - JPA InterfaceRepresents a bound type, usually an entity that appears in the from clause, but may also be an embeddable belonging to an entity in the from clause.) represent FROM variables.  FROM variable expressions are considered as basic paths and also serve as a starting point for building more complex paths through navigation.

Giving a Path instance, a child Path expression (which represents navigation from the parent path through a persistent field or property), can be constructed by the getPath.get(attributeName) - JPA MethodCreate a path corresponding to the referenced attribute. method:

  // FROM Variable Paths:
  Rootjavax.persistence.criteria.Root - JPA InterfaceA root type in the from clause.<Country> country = query.fromAbstractQuery.from(entityClass) - JPA MethodCreate and add a query root corresponding to the given entity,
 forming a cartesian product with any existing roots.(Country.class);
  Joinjavax.persistence.criteria.Join - JPA InterfaceA join to an entity, embeddable, or basic type.<Country, Country> neighborCountry = country.joinFrom.join(attributeName) - JPA MethodCreate an inner join to the specified attribute.("neighbors");

  // Navigation Paths:
  Pathjavax.persistence.criteria.Path - JPA InterfaceRepresents a simple or compound attribute path from a
 bound type or collection, and is a "primitive" expression.<String> countryName = country.getPath.get(attributeName) - JPA MethodCreate a path corresponding to the referenced attribute.("name");
  Pathjavax.persistence.criteria.Path - JPA InterfaceRepresents a simple or compound attribute path from a
 bound type or collection, and is a "primitive" expression.<City> capital = country.getPath.get(attributeName) - JPA MethodCreate a path corresponding to the referenced attribute.("capital");
  Pathjavax.persistence.criteria.Path - JPA InterfaceRepresents a simple or compound attribute path from a
 bound type or collection, and is a "primitive" expression.<String> captialName = capital.getPath.get(map) - JPA MethodCreate a path corresponding to the referenced
  map-valued attribute.("name");

The path expressions in the above code can be divided into two main groups:

Type Expressions

Entity type expressions can be constructed by the Pathjavax.persistence.criteria.Path - JPA InterfaceRepresents a simple or compound attribute path from a bound type or collection, and is a "primitive" expression.'s typePath.type() - JPA MethodCreate an expression corresponding to the type of the path. method. For example, the following criteria expression checks if the type of a specified entity e is not Country.

  Predicatejavax.persistence.criteria.Predicate - JPA InterfaceThe type of a simple or compound predicate: a conjunction or
 disjunction of restrictions. p = cb.notEqualCriteriaBuilder.notEqual(x,y) - JPA MethodCreate a predicate for testing the arguments for inequality.(e.typePath.type() - JPA MethodCreate an expression corresponding to the type of the path.(), cb.literalCriteriaBuilder.literal(value) - JPA MethodCreate an expression for a literal.(Country.class));

In the above example, the comparison is between the type of the e object (which may represent any path including a root or a join) and the entity type Country (a criteria literal).