24

I have taken a look at JPA 2.0 Criteria API, but I found it to be too cumbersome unlike Hibernate Criteria. Is there any good reason to use JPA 2.0 Criteria API rather than using JPA-QL? Thanks for your advise.

Joshua Partogi
  • 16,167
  • 14
  • 53
  • 75
  • This question is essentially a duplicate of [hibernate query language or using criteria](http://stackoverflow.com/questions/2905273/hibernate-query-language-or-using-criteria) or [Hibernate: Criteria vs. HQL](http://stackoverflow.com/questions/197474/hibernate-criteria-vs-hql) since the pros ans cons are the same. – Pascal Thivent Aug 06 '10 at 07:05
  • Not really. JPA 2.0 criteria API is not as simple as Hibernate criteria. I've used Hibernate criteria before, and I feel JPA 2.0 criteria API feels a little bit cumbersome. – Joshua Partogi Aug 06 '10 at 07:24
  • Actually, I omitted a very important difference that I will cover in an answer. – Pascal Thivent Aug 06 '10 at 08:45

4 Answers4

36

Like the Hibernate Criteria API, the JPA 2.0 Criteria API is especially nice to build queries dynamically, to handle cases where the query structure varies depending upon runtime conditions.

But there is more. While being more verbose than Hibernate's Criteria API, the JPA Criteria API allows to build typesafe queries (if you use the Metamodel API). Below an example:

EntityManager em = ...
QueryBuilder qb = em.getQueryBuilder();
CriteriaQuery<Person> c = qb.createQuery(Person.class);
Root<Person> p = c.from(Person.class);
Predicate condition = qb.gt(p.get(Person_.age), 20);
c.where(condition);
TypedQuery<Person> q = em.createQuery(c); 
List<Person> result = q.getResultList();

In the above snippet, the following would raise a compilation error for example:

Predicate condition = qb.gt(p.get(Person_.age, "xyz"));

In case you wonder, Person_ is the static, instantiated, canonical metamodel class corresponding to the original Person entity class (generated by an annotation processor). It provides a strongly typed alternative to a runtime reflection based approach:

Field field = Person.class.getField("age");

Pros:

  • Type safety, compile time verification!
    • Prohibits the construction of queries that are syntactically incorrect.
    • Can raise a compilation error after a refactoring.
    • Provides out of the box support for auto-completion
  • Better suited for dynamic queries.

Cons:

  • More verbose.
  • Less readable.

I feel in general more comfortable with JPQL but the type safety of the Criteria API is a major difference with JPQL (and also the Hibernate Criteria API).

See also

Related answers

Community
  • 1
  • 1
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
  • Thanks for the explanation Pascal. I wouldn't have thought of that. – Joshua Partogi Aug 06 '10 at 10:55
  • I have one question, why in the code you are not using the core I have found in other examples: Metamodel m = em.getMetamodel(); EntityType Pet_ = m.entity(Pet.class); – will824 May 03 '11 at 22:12
4

JPA 2.0 Criteria API is The Object-based API for building queries. I think it can play a good job when you have a dynamic query which can become more readable as follows

cq.select(...)
  .where(...)
  .orderBy(...)
  .groupBy(...);

But when using static query prefer To use an externalized, maintainable and readable file

<entity-mappings>
    ...
    <named-query name="ORDER">
       <query>
           <![CDATA[
               from
                   Order
           ]]>
       </query>
    </named-query>
    <named-query name="ORDER_WITH_LINE_ITEM">
       <query>
           <![CDATA[
               from
                   Order o
               inner join fetch 
                   o.lineItemList
           ]]>
       </query>
    </named-query>
    ...
</entity-mappings>

If you have a modularized application use one xml file for each module as follows

br
   com
       ar
           moduleA
               model
                   repository
                       moduleA.xml
           moduleB
               model
                   repository
                       moduleB.xml               
           moduleC
               model
                   repository
                       moduleC.xml

Then you define your mappinf-file element

<mapping-file>br/com/ar/moduleA/model/repository/moduleA.xml</mapping-file>
<mapping-file>br/com/ar/moduleB/model/repository/moduleB.xml</mapping-file>
<mapping-file>br/com/ar/moduleC/model/repository/moduleC.xml</mapping-file>
Arthur Ronald
  • 33,349
  • 20
  • 110
  • 136
1

JPA 2 Criteria can be used in statically typed form if you generate the entity metamodel. It is more verbose than JPQL, but is statically typed and supports dynamic query construction directly.

The benefits of a statically typed query language is that you can catch more errors at compile time and IDE features like autocomplete can be used as well.

Timo Westkämper
  • 21,824
  • 5
  • 78
  • 111
0

For me the real world example where JPA2 shines is in when you need to create a query based on input from a user. I am not talking about a very simple where with one parameter. I mean when you have made an advanced search option in your application. One that requires joins when a certain parameter is filled. You don't what to concatenate your HQL or SQL to include a large set of parameters, extra joins and functions. Custom SQL requires a lot of tests to prove it works. Adding extra search options to HQL and SQL requires a lot of rework whereas this might be simpler in JPA.

Ivo Limmen
  • 3,095
  • 1
  • 26
  • 23