March 8, 2021
Hot Topics:

Criteria Queries in JPA 2.0 and Hibernate: The APIs Have It

  • By Nitin KL, Sangeetha S
  • Send Email »
  • More Articles »

One of the main areas in which version 2.0 of the Java Persistence API (JPA) improved from the previous version is criteria queries. Not only was its query language enhanced, but JPA 2.0 also offers new APIs for criteria queries. The most helpful of these APIs, however, may be one that was introduced as part of another ORM solution, Hibernate 3.0.

Before the introduction of Hibernate's criteria query API in version 3.0, both JPA and Hibernate offered very powerful object-oriented querying languages for performing queries on databases. JPA offered the Java Persistence Query Language (JPQL), while Hibernate offered the Hibernate Query Language (HQL). HQL queries are case insensitive except for Java classes and properties, and both languages use the string-based approach to define queries. However, the string-based approach has a major limitation: the syntax errors in the queries are not detected during compile time because the compiler checks only for strings.

The criteria query API overcomes this limitation by enabling the programmer to define queries through the construction of object-based query definitions. The criteria query API helps in creating structured and nested queries, provides compile time safety, and most importantly, never allows the programmer to build queries that have incorrect syntax.

In this article, we present a brief comparison of the criteria queries features in JPA 2 and Hibernate. In particular, we explore JPA 2's Metamodel APIs for criteria queries, an innovative feature that is not available in Hibernate.

Criteria Queries in JPA 2

The Java Persistence Criteria API's data model is based on the abstract persistence schema of entities, their embedded objects, and their relationships. The Java Persistence Criteria API is closely related to JPQL (a powerful feature that is largely responsible for the success of JPA) and designed in a way to allow similar invocations.

The simple criteria query shown below creates a criteria object for the Employee class and returns all the instances of Employee:

....@PersistenceContextEntityManager entityManager;CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();CriteriaQuery<Employee> cqEmp = criteriaBuilder.createQuery(Employee.class);Root<Employee> employee = cqEmp.from(Employee.class);cqEmp.select(employee);TypeQuery<Employee>  typeQuery = entityManager.createQuery(cqEmp);List<Employee> employees = typeQuery.getResultList();....

What happens in the code is first an object of CriteriaBuilder is created with EntityManager. A query object is created on the CriteriaBuilder with the CriteriaQuery interface. This query object is used to specify the attributes of the query. Then the root of the query is obtained from the query object. Next, the type of query (select, in this example) is specified on the query object. The query object created is prepared for execution by specifying the type of query result. Finally, the query is executed with the invocation of the getResultList() method, where the result type (a collection of employee entities) is stored in a List object.

The equivalent query in JPQL would be:


Metamodel in JPA 2

Java Persistence Criteria queries are based on a metamodel of the persistence unit's managed classes. The abstract persistence schema is composed of metamodel objects over which the Criteria API operates. A metamodel class models the persistent state and relationships of the corresponding managed class, which is the advantage of criteria queries in JPA 2.

The JPA 2 specification details how to represent the meta information of a persistent entity in a metamodel class. If this is achieved strictly by an application, it is referred to as Canonical Metamodel. A canonical metamodel class is static if all the members of the class are static and public. However, if a developer creates metamodel classes on his/her own, they are considered Non Canonical Metamodel classes.

Let's try to understand metamodel classes by using the same Employee example as in the previous section. The Employee entity class has three persistence fields: empId, empName and empUnit.

package com.empdetails;....@Entitypublic class Employee {@Idprotected String empId;protected String empName;protected String empUnit;...}

The corresponding metamodel class could be:

package com.empdetails;....@Static Metamodel(Employee.class)public class Employee_ {public static volatile SingularAttribute<Employee, String> empId;public static volatile SingularAttribute<Employee, String> empName;public static volatile SingularAttribute<Employee, String> empUnit;}

The metamodel can be used as follows:

@PersistenceContextEntityManager entityManager;CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();CriteriaQuery query = criteriaBuilder.createQuery(Employee.class);Root<Employee> emp = query.from(Employee.class);// Get the metamodel of Employee entityEntityType<Employee> Employee_ = emp.getModel();

The JPA 2 specification provides a set of interfaces for dynamically accessing the metamodel corresponding to the persistence unit's managed classes. The javax.persistence.metamodel interfaces enable developers to access dynamically the metamodel of the persistent state and relationships of a persistence unit's managed classes. The metamodel can be accessed through the EntityManagerFactory or EntityManager getMetaModel() methods. If the metamodel class has to be obtained first, then use this code:

@PersistenceContextEntityManager entityManager;Metamodel model = entityManager.getMetamodel();// Get the metamodel before the ROOTEntityType<Employee> Employee_ = model.entity(Employee.class);

Page 1 of 2

This article was originally published on July 20, 2010

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date