分享

Hibernate: Criteria vs. HQL

 燮羽 2010-11-27

What are the pros and cons of using Criteria or HQL?
The Criteria API is a nice object-oriented way to express queries in Hibernate, but sometimes Criteria Queries are more difficult to understand/build than HQL.

When do you use Criteria and when HQL? What do you prefer in which use cases? Or is it just a matter of taste?


I mostly prefer Criteria Queries for dynamic queries. For example it is much easier to add some ordering dynamically or leave some parts (e.g. restrictions) out depending on some parameter.

On the other hand I'm using HQL for static and complex queries, because it's much easier to understand/read HQL. Also, HQL is a bit more powerful, I think, e.g. for different join types.

There is a difference in terms of performance between HQL and criteriaQuery, everytime you fire a query using criteriaQuery, it creates a new alias for the table name which does not reflect in the last queried cache for any DB. This leads to an overhead of compiling the generated SQL, taking more time to execute.

Regarding fetching strategies [http://www./315.html]

  • Criteria respects the laziness settings in your mappings and guarantees that what you want loaded is loaded. This means one Criteria query might result in several SQL immediate SELECT statements to fetch the subgraph with all non-lazy mapped associations and collections. If you want to change the "how" and even the "what", use setFetchMode() to enable or disable outer join fetching for a particular collection or association. Criteria queries also completely respect the fetching strategy (join vs select vs subselect).
  • HQL respects the laziness settings in your mappings and guarantees that what you want loaded is loaded. This means one HQL query might result in several SQL immediate SELECT statements to fetch the subgraph with all non-lazy mapped associations and collections. If you want to change the "how" and even the "what", use LEFT JOIN FETCH to enable outer-join fetching for a particular collection or nullable many-to-one or one-to-one association, or JOIN FETCH to enable inner join fetching for a non-nullable many-to-one or one-to-one association. HQL queries do not respect any fetch="join" defined in the mapping document.

Criteria is an object-oriented API, while HQL means string concatenation. That means all of the benefits of object-orientedness apply:

  1. All else being equal, the OO version is somewhat less prone to error. Any old string could get appended into the HQL query, whereas only valid Criteria objects can make it into a Criteria tree. Effectively, the Criteria classes are more constrained.
  2. With auto-complete, the OO is more discoverable (and thus easier to use, for me at least). You don't necessarily need to remember which parts of the query go where; the IDE can help you
  3. You also don't need to remember the particulars of the syntax (like which symbols go where). All you need to know is how to call methods and create objects.
Since HQL is very much like SQL (which most devs know very well already) then these "don't have to remember" arguments don't carry as much weight. If HQL was more different, then this would be more importatnt.
These arguments don't hold water (with respect to HQL). It does not have to involve string concatenation. That the OO version is less prone to errors is unsubstantiated. It is equally prone to errors but of a different kind. The effort of knowing what methods to call is not that much different from knowing what symbols to call in HQL (I mean, seriously, we are not solving PDEs here.) – luis.espinal Oct 12 at 13:42

HQL is much easier to read, easier to debug using tools like the Eclipse Hibernate plugin, and easier to log. Criteria queries are better for building dynamic queries where a lot of the behavior is determined at runtime. If you don't know SQL, I could understand using Criteria queries, but overall I prefer HQL if I know what I want upfront.

I usually use Criteria when I don't know what the inputs will be used on which pieces of data. Like on a search form where the user can enter any of 1 to 50 items and I dunno what they will be searching for. It is very easy to just append more to the criteria as I go through checking for what the user is searching for. I think it would be a little more troublesome to put an HQL query in that circumstance. HQL is great though when I know exactly what I want.

 

For me the biggest win on Criteria is the Example API, where you can pass an object and hibernate will build a query based on those object properties.

Besides that, the criteria API has its quirks (I believe the hibernate team is reworking the api), like:

  • a criteria.createAlias("obj") forces a inner join instead of a possible outer join
  • you can't create the same alias two times
  • some sql clauses have no simple criteria counterpart (like a subselect)
  • etc.

I tend to use HQL when I want queries similar to sql (delete from Users where status='blocked'), and I tend to use criteria when I don't want to use string appending.

Another advantage of HQL is that you can define all your queries before hand, and even externalise them to a file or so.


 

To use the best of both worlds, the expressivity and conciseness of HQL and the dynamic nature of Criteria consider using Querydsl : http://source./display/querydsl/Querydsl

Querydsl supports JPA/Hibernate, JDO, SQL and Collections.

I am the maintainer of Querydsl, so this answer is biased.


 

Criteria are the only way to specify natural key lookups that take advantage of the special optimization in the second level query cache. HQL does not have any way to specify the necessary hint.

You can find some more info here:


 

For me Criteria is a quite easy to Understand and making Dynamic queries. But the flaw i say so far is that It loads all many-one etc relations because we have only three types of FetchModes i.e Select, Proxy and Default and in all these cases it loads many-one (may be i am wrong if so help me out :))

2nd issue with Criteria is that it loads complete object i.e if i want to just load EmpName of an employee it wont come up with this insted it come up with complete Employee object and i can get EmpName from it due to this it really work bad in reporting. where as HQL just load(did't load association/relations) what u want so increase performance many times.

One feature of Criteria is that it will safe u from SQL Injection because of its dynamic query generation where as in HQL as ur queries are either fixed or parameterised so are not safe from SQL Injection.

Also if you write HQL in ur aspx.cs files, then you are tightly coupled with ur DAL.

Overall my conclusion is that there are places where u can't live without HQL like reports so use them else Criteria is more easy to manage.

Zafar Ullah www.hyperlinksolutions.net http://barchitect.


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多