A new colleague has just suggested using named HQL queries in Hibernate with annotations (i.e. @NamedQuery) inste开发者_StackOverflowad of embedding HQL in our XxxxRepository classes.
What I'd like to know is whether using the annotation provides any advantage except for centralising queries?
In particular, is there some performances gain, for instance because the query is only parsed once when the class is loaded rather than every time the Repository method is executed?
from Pro EJB 3 (Mike Keith):
"...we recommend named queries whenever possible. Persistence providers will often take steps to precompile JPQL named queries to SQL as part of the deployment or initialization phase of an application."
Although this book is on JPA, the general advice applies to Hibernate. However, since Hibernate caches parsed HQL/JPQL, you probably won't see a big performance gain. Another advantage of using named queries is that it gives you the option to override a query using a mapping file at deployment time without having to rebuild your application; useful if you need to tweak a query in production.
Apart from any possible performance gain, I believe another advantage would be that by using HQL queries with annotations you can protect yourself from SQL Injection attacks.
For a web application, this is important if the query contains any user input data.
http://en.wikipedia.org/wiki/SQL_injection
Lars' comment regarding SQL injection is potentially misleading, although I don't think it was his intention, and I wanted to provide a little more context so that the comment isn't misunderstood.
It's true that named queries are parameterized by specification, and the use of named parameters is one step in guarding against SQL injection. However, it does not fully protect from SQL injection (refer to his link for more). The wording of the comment suggests that the use of named queries is the only necessary step in guarding against injection attacks. In reality, normal queries can (and should) be parameterized and will provide the exact same level of insulation from injection attack as named queries, and parameterizing your queries is only one of a number of necessary steps in thwarting injection attacks.
To add to Lars' comment about webapps, note that it's important to scrub data to guard against injection attacks regardless of whether the application is externally facing or not, or whether the input data is from a user or from another database (or even the same database).
Personally, I think the performance gain is less important than the fact that your hql queries are parsed during server startup, providing you with instant messages if your hql query is wrong.
I prefer to catch these errors before testing instead of during.
Last time, during testing, I came upon a query in the code that didn't work, had in fact never worked, because of CaSiNg. This would have immediately become apparent during server startup, when using named queries.
And, ofcourse, I dislike having my HQL mixed in with Java code.
精彩评论