Paths and Types in JPQL and Criteria API

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

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

Instances of user-defined persistent classes can participate in direct comparisons by using the = and <> operators. However, they are more often used in JPQL path expressions that navigate to values of simple types, such as numbers, booleans, strings, and dates.

Values of simple types are more useful in queries because they have special operators and functions (for example, for strings and numbers). They can also be compared by all six comparison operators and used for ordering.

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

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

A path expression whose result is a user-defined persistent class can be extended by reusing the dot (.) operator. For example, c.capital.name is a nested path expression that navigates from the Capital entity to its name field. A path expression can be extended only if its result is also a user-defined persistent class. The dot (.) operator cannot be applied to collections, maps, or values of simple types (such as numbers, booleans, strings, and dates).

For a path expression to be valid, the user-defined persistent class must contain a persistent field or property with a matching name. The path expression 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 iterates over all the Country objects in the database.

For a country with no capital city, such as Nauru, c.capital evaluates 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 through a null reference. In JPQL, the current FROM variable (or FROM tuple, when there are multiple variables) is skipped. To better understand how this works, consider the equivalent JOIN query.

Entity Type expressions

The TYPE operator returns the type of a specified argument, similar to the getClass method of java.lang.Object in Java.

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

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

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

Criteria query paths and types

Paths and navigation are represented in the JPA Criteria API by the Pathjakarta.persistence.criteria.PathRepresents a simple or compound attribute path from a bound type or collection, and is a "primitive" expression. interface and its subinterfaces, such as Fromjakarta.persistence.criteria.FromRepresents 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., Rootjakarta.persistence.criteria.RootA root type in the from clause., and Joinjakarta.persistence.criteria.JoinA join to an entity, embeddable, or basic type..

Path expressions

The Rootjakarta.persistence.criteria.RootA root type in the from clause. and Joinjakarta.persistence.criteria.JoinA join to an entity, embeddable, or basic type. interfaces, which are subinterfaces of Fromjakarta.persistence.criteria.FromRepresents 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 basic paths and serve as a starting point for building more complex paths through navigation.

Given a Path instance, you can construct a child Path expression, which represents navigation from the parent path through a persistent field or property, by using the getjakarta.persistence.criteria.Path.get(String)Create a path corresponding to the referenced attribute. method:

  // FROM Variable Paths:
  Rootjakarta.persistence.criteria.RootA root type in the from clause.<Country> country = query.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.(Country.class);
  Joinjakarta.persistence.criteria.JoinA join to an entity, embeddable, or basic type.<Country, Country> neighborCountry = country.joinjakarta.persistence.criteria.From.join(String)Create an inner join to the specified attribute.("neighbors");
  // Navigation Paths:
  Pathjakarta.persistence.criteria.PathRepresents a simple or compound attribute path from a bound type or collection, and is a "primitive" expression.<String> countryName = country.getjakarta.persistence.criteria.Path.get(String)Create a path corresponding to the referenced attribute.("name");
  Pathjakarta.persistence.criteria.PathRepresents a simple or compound attribute path from a bound type or collection, and is a "primitive" expression.<City> capital = country.getjakarta.persistence.criteria.Path.get(String)Create a path corresponding to the referenced attribute.("capital");
  Pathjakarta.persistence.criteria.PathRepresents a simple or compound attribute path from a bound type or collection, and is a "primitive" expression.<String> captialName = capital.getjakarta.persistence.criteria.Path.get(MapAttribute)Create a path corresponding to the referenced map-valued attribute.("name");

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

Type expressions

Entity type expressions can be constructed by using the typejakarta.persistence.criteria.Path.type()Create an expression corresponding to the type of the path. method of the Pathjakarta.persistence.criteria.PathRepresents a simple or compound attribute path from a bound type or collection, and is a "primitive" expression. interface. For example, the following criteria expression checks if the type of a specified entity e is not Country.

  Predicatejakarta.persistence.criteria.PredicateThe type of a simple or compound predicate: a conjunction or disjunction of restrictions. p = cb.notEqualjakarta.persistence.criteria.CriteriaBuilder.notEqual(Expression,Expression)Create a predicate for testing the arguments for inequality.(e.typejakarta.persistence.criteria.Path.type()Create an expression corresponding to the type of the path.(), cb.literaljakarta.persistence.criteria.CriteriaBuilder.literal(T)Create an expression for a literal.(Country.class));

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