2

I'm trying to compare Hibernate Criteria to named queries for performance. i'm aware it all depends on the actual query itself and the last word is on how they profile in runtime. still, trying to sort out what goes into each.

i tried to organize the Q in two parts & looking for verification/correction on both:

PART-1 -- how Hibernate Criteria and named queries work basically:

Criteria works on parameters. In runtime, the query doesn`t need parsing-- has several search and "present-in-form" params like order the results, return them as scrollable etc. Haven't read/verified this, but Criteria works by indexes on fields (based on the parameters set on them) to make it all faster.

So, the advantage of Criteria compared to plain HQL is its speed during execution.

Named queries have the same advantage over HQL-- the query is parsed once at start-up. Then executed from wherever necessary in the application.

PART-2 -- comparing the two:

So in this picture,

how do Criteria and named-queries compare to one another?

Criteria works well for complicated queries across multiple tables and multiple params-- has the means to optimize and thus make the query fast(?)

named-queries have the advantage of "define-once-use-everywhere" and are quite alright for "light" queries-- less complicated searches with small amount of params typically on a single table. even better on frequent queries.

Note: seen the very useful Hibernate Criteria vs HQL: which is faster? among some other discussions.

TIA.

Community
  • 1
  • 1
Roam
  • 4,511
  • 9
  • 36
  • 68

2 Answers2

9

You don't choose one over the other based on performance. In the end, it becomes a SQL query anyway, and what matters is the performance of the SQL query.

Executing a SQL query is orders of magnitudes slower than parsing a HQL query and transforming it to SQL. So even if you don't use a named query, the performance won't be significantly worse.

You choose criteria over HQL based on capabilities and readability.

If you want something readable, use a HQL query.

If you want to compose a query dynamically, based on various, optional, search criteria, then the Criteria API allows that, and is more convenient than dynamically composing an HQL query.

JB Nizet
  • 633,450
  • 80
  • 1,108
  • 1,174
6

Criteria, in theory should have less overhead than an HQL query (except for named queries, which I'll get to). This is because Criteria doesn't need to parse anything. HQL queries are parsed with an ANTLR-based parser and then the resulting AST is turned into SQL. However, with HQL/JPAQL you can define named queries, where the SQL is generated when the SessionFactory starts up. In theory, named queries have less overhead than Criteria. So, in terms of SQL-generation overhead we have:

  1. Named HQL/JPAQL Query - SQL generation happens only once.
  2. Criteria - No need to parse before generating.
  3. (non-named) HQL/JPAQL Query - Parse, then generate. That said, choosing a query technique based on the overhead of parsing and SQL generation is probably a mistake in my opinion. This overhead is typically very small when compared to performing a real query on a real database server with real data. If this overhead does actually show up when profiling the app then maybe you should switch to a named query.

Here are the things I consider when deciding between Criteria and HQL/JPAQL:

  • First, you have to decide if you're OK with having a dependency on Hibernate-proprietary API in your code. JPA doesn't have Criteria.
  • Criteria is really good at handling many optional search parameters such as you might find on a typical web page with a multi-parameter 'search form'. With HQL, developers tend to tack on where clause expressions with StringBuilder (avoid this!). With Criteria, you don't need to do that.
  • HQL/JPAQL can be used for most other things, because the code tends to be smaller and easier for developers to understand.
  • Really frequent queries can be turned into named queries if you use HQL. I prefer to do this later, after some profiling.
Sagar Panda
  • 602
  • 4
  • 17