3

I'm working on J2EE 6 codebase that uses Hibernate as its persistence provider. My experience lies more in Spring and I'm quite new to JPA annotations and similar, but I've noticed a lot of this in all the entity classes, and it surprises me - I thought @NamedQuery were more for complex SQL? Surely these simple selects (and joins that are defined in the hibernate mappings) can be done without writing out the SQL?

In the Entity:
@NamedQueries({
@NamedQuery(name = "DealRaw.findByrawUrl", query = "SELECT d FROM DealRaw d WHERE d.rawUrl = :rawUrl"),
@NamedQuery(name = "DealRaw.findByState", query = "SELECT d FROM DealRaw d WHERE d.state = :state"),
.... etc ....
})

and then

In the Service Class
Query qR=_em.createNamedQuery("DealRaw.findByrawUrl");  //_em is an EntityManager
qR.setParameter("rawUrl", value);
List<DealRaw> dRs=(List <DealRaw>)qR.getResultList();
Charles
  • 50,943
  • 13
  • 104
  • 142
Peter
  • 29,498
  • 21
  • 89
  • 122

3 Answers3

2

These queries are not SQL queries, but JPQL queries. And you may put any kind of query inside a named query, complex or not.

They all have the same advantages :

  • the JPA engine parses and validates the query at startup time, and may cache the result of the parsing to avoid parsing it again and again.
  • the same query may easily be used at several places in the code (although that would be questionable design)

They all have the same disadvantage, IMO : the query is not defined where it is used, and the code is thus harder to understand.

Whether those queries are named or not, you will have to write these queries to execute them. The only other ways to load entities are to find them using their ID (which is not the case here), or to navigate from one entity to another using associations (which is not the case either).

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Thanks, good explanation. Is it true that NamedQueries only work on classes that are annotated with @Entity? Given your answer I'd like to put some of the more complicated ones that hit multiple tables in a DAO – Peter Oct 31 '11 at 23:23
  • AFAIK, they can only be puton entities and mapped super classes – JB Nizet Nov 01 '11 at 07:51
1

Why not use Criteria instead of using NamedQuery? Filtering will be a lot easier. In some cases creating the Criteria gets very confusing and hard, however for single column I believe it is the easiest option.

flavio_yama
  • 313
  • 1
  • 4
  • 10
  • curious what advantage Criteria would have over NamedQuery? – digitaljoel Oct 31 '11 at 18:53
  • Criteria is Type safe NamedQuery are just pre made selects and so they are not. – Cristiano Fontes Oct 31 '11 at 19:52
  • as JB Nizet said, the NamedQuery is parsed at startup time, so if you run any unit tests you'll quickly know if your query is wonky. Also, a decent IDE like STS will alert you to issues in your query as you write it. Don't get me wrong, I believe there are valid uses for Named Queries and for Criteria. I find when creating a criteria query of any complexity I have to write the regular query first and then convert it to a criteria query just to get through it. – digitaljoel Nov 01 '11 at 02:20
  • List cats = sess.createCriteria(Cat.class).add(Restrictions.like("name", "Fritz%") ).list(); One example from the Hibernate documentation. – flavio_yama Nov 01 '11 at 18:53
  • As for the advantages, there is a big discussion over here on HQL vs Criteria: http://stackoverflow.com/questions/197474/hibernate-criteria-vs-hql I'd say it is more dependent on what your needs are. For complexes queries, HQL is a lot better. – flavio_yama Nov 01 '11 at 19:06
1

As JB Nizet said, in order to find the result set, you're going to have to write the queries somewhere.

One advantage to having them as a NamedQuery (or CriteriaQuery if that's your thing) is that you are protecting yourself against SQL injection. If the query is created on the fly in the code with string concatenation such as String query = "SELECT d FROM DealRaw d WHERE d.rawUrl = '" + rawUrl + "'"; or even using named parameters, some programmer in the future may come along and modify the query in a way that allows SQL injection (as in the example).

Yes, there are ways to use named parameters in a query constructed in code with concatenation, but that doesn't protect you as much as a pre-defined Named Query.

digitaljoel
  • 26,265
  • 15
  • 89
  • 115