One of the important feature in JPA 2.0 is using the Criteria API for forming the SQL queries. If you would have worked with the JPA 1.0 version, you must be familiar with the Java Persistence Query Language (JQL) which is similar to writing the SQL queries. This approach is good for the developers who are much familiar with SQL syntax and programming, for the Java developers who are not comfortable with SQL will leads to lot of syntax error. One of the dis-advantage with JQL is, it can not capture the grammar errors at the compile time. If you have errors at SQL, it is thrown errors at the run time. Criteria API solves this problem by providing he strongly typed metamodel objects (Read : Generate MetaModel Using Eclipse or Ant) for writing the queries.
For the beginners who are not familiar with the JPA concepts, please read our article on Introduction to JPA before start reading this tutorial.
JPA Criteria API vs JPQL
JPQL queries are defined as the SQL strings. The only difference with the normal SQL is that JPQL has its own grammar for querying the datbase. For simple static queries, using JPQL is preferred. It will be easy for you to write a query instead of forming it using the CriteriaBuilder. When you build query at run time, writing plain SQL query would have unnecessary string concatenation operations which will leads to lot of syntax issues which can not be detected at the compile time.
String based JPQL queries and JPA criteria based queries are equivalent in power and performance. Choosing one method over the other is also a matter of personal choice. If you choose for your projects, please consider the pros and cons of each method. However, JPA itself recommends using the Criteria API.
Problem with JPQL Query
Lets look at the below code:
EntityManager em = …;
String jpql = "select e from Employee where e.id > 20";
Query query = em.createQuery(jpql);
List result = query.getResultList();
If you look at the above code, it has one error. The correct code is below:
String jpql = "select e from Employee e where e.id > 20";
These errors are caught at the run time. That is the main dis-advantage of using the JPQL query.
A Simple JPA Criteria Query
The following query represents a simple JPQL query:
select * from employee e
The same query can be built using the JPA criteria API as below:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Employee> e = cb.createQuery(Employee.class);
Root<Employee> ee = e.from(Employee.class);
CriteriaBuilder is the main factory for getting the criteria queries. You can get this object by using the EntityManagerFactory or EntityManager interface.
Typesafe Criteria Query with Metamodel
I have explained in the previous post about the metamodel. It helps you to understand the metamodel and requires understanding the below code.
EntityManager em = …
CriteriaBuilder qb = em.getCriteriaBuilder();
CriteriaQuery<Employee> c = qb.createQuery(Employee.class);
Root<Employee> p = c.from(Employee.class);
Predicate condition = qb.gt(p.get(Employee_.id), 20);
TypedQuery<Employee> q = em.createQuery(c);
List<Employee> result = q.getResultList();
The above code has many new things which is introduced from JPA 2. But, here we have to understand the TypedQuery which is the important concept for making the query is strongly typed. Also look at the “Employee_” which is generated as part of the metamodel.