29

Is there a heuristic/best practice/ruleset for a decision between the Criteria API and NamedQuery?

My thoughts so far :
Named queries are generally more readable. Criteria queries are more flexible.
Both are precompiled. I tend to rely on using named queries as long as possible, then changing to criteria.

But maybe the urge to "flexify" the query by using the criteria API is a hint to suboptimal design (i.e. separation of concerns)?

Thank you

kostja
  • 60,521
  • 48
  • 179
  • 224

5 Answers5

37

Named queries are more optimal (they are parsed/prepared once). Criteria queries are dynamic, (they are not precompiled, although some JPA providers such as EclipseLink maintain a criteria prepare cache).

I would use criteria only for dynamic queries.

James
  • 17,965
  • 11
  • 91
  • 146
  • 5
    I like to only use Criteria. Combine the Criteria API with a metamodel of the entity and you can fully abandon the use of String and produce strong typed code, for a Java geek that is real fun! However, I found [this](http://milestonenext.blogspot.se/2013/02/jpql-vs-criteria.html) test that actually show that Criteria perform even worse than JPQL! – Martin Andersson Apr 18 '13 at 07:52
  • 1
    Technically that performance test did not use the generated Metamodel which the best part about JPA Criteria API. I had great difficulty in the beginning switching from Hibernate Criteria to JPA, but now I really prefer the JPA one. – Yinzara Mar 16 '14 at 03:41
  • @Yinzara I am late to the part but when you say JPA Criteria API what do you mean? Isn't JPA the spec and hibernate one of the implementation/provider? Which particular provider would you be talking about when you say you prefer JPA Criteria to Hibernate? – Willa Mar 16 '18 at 21:15
  • This is a pretty old thread :) but the thread was not comparing "Hibernate" to "JPA". It was comparing using the Hibernate Criteria API vs Hibernate Named Queries. Generally Criteria queries are really good when you want to build a dynamic query. Named queries are better for a query that only had parameters that change but not the structure as it's parsed once and doesn't have to be rebuilt each time you use it. Using the JPA criteria metamodel is probably the best way of all but that requires generated code. – Yinzara Mar 19 '18 at 19:05
10

Criteria queries are a good choice when a query must be generated dynamically, based of variable and multiple search criteria, for example.

For static queries, JPQL is much more readable, and I prefer using them than criteria queries. You could lose some safety, but the unit tests should make you more confident.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
4

Another viewpoint is that although criteria query is not so readable, it is typesafe, therefore provides you compile time type checking. If you change the database in projects where there are many entities and many queries, it is really helpful to see at compile time what queries went wrong because of the change.

On the other hand, I'm not sure that is more beneficial than the simpleness of JPQL

3

I actually went through the Hibernate (4.3.0-SNAPSHOT) source and the EclipseLink (2.5.0-SNAPSHOT) source and looked through the JPA implementation in each.

EclipseLink is clearly not thread safe in the manner you describe. Specifically it tries to recalculate joins repeatedly.

Hibernate's implementation looks thread safe to me. I'm not 100% sure, but it does seem to be. I would say that this is not guaranteed to be true in the future since it isn't specified.

However, I will warn you, I don't think you're going to gain much. From what I'm looking at, much of the compilation of the query is actually done during the "createQuery" phase so you wouldn't even gain much caching the results.

Yinzara
  • 783
  • 8
  • 15
2

JPA also provides a way for building static queries, as named queries, using the @NamedQuery and @NamedQueries annotations. It is considered to be a good practice in JPA to prefer named queries over dynamic queries when possible. From http://www.objectdb.com/java/jpa/query/api