3.3 Better Ways to Build Queries

     

As mentioned earlier, HQL lets you go beyond the use of JDBC-style query placeholders to get parameters conveniently into your queries. The features discussed in this section can make your programs much easier to read and maintain.

Use named parameters to control queries and move the query text completely outside of your Java source code.

3.3.1 Why do I care?

Well, I've already promised that this will make your programs easier to write, read, and update. In fact, if these features weren't available in Hibernate, I would have been less eager to adopt it, because they've been part of my own (even more) lightweight O/R layer for years .

Named parameters make code easier to understand because the purpose of the parameter is clear both within the query itself and within the Java code that is setting it up. This self-documenting nature is valuable in itself, but it also reduces the potential for error by freeing you from counting commas and question marks, and it can modestly improve efficiency by letting you use the same parameter more than once in a single query.

NOTE

If you haven't yet had to deal with this, trust me, it's well worth avoiding.

Keeping the queries out of Java source code makes them much easier to read and edit because they aren't giant concatenated series of Java strings spread across multiple lines and interleaved with extraneous quotation marks, backslashes, and other Java punctuation. Typing them the first time is bad enough, but if you've ever had to perform significant surgery on a query embedded in a program in this way, you will have had your fill of moving quotation marks and plus signs around to try to get the lines to break in nice places again.

3.3.2 How do I do that?

The key to both of these capabilities in Hibernate is the Query interface. We'll start by changing our query to use a named parameter (Example 3-8). (This isn't nearly as big a deal for a query with a single parameter like this one, but it's worth getting into the habit right away. You'll be very thankful when you start working with the light- dimming queries that power your real projects!)

Example 3-8. Revising our query to use a named parameter
 public static List tracksNoLongerThan(Time length, Session session)      throws HibernateException  {      Query query = session.createQuery("from com.oreilly.hh.Track as track " +                                        "where track.playTime <= :length");      query.setTime("length", length);      return query.list();  } 

Named parameters are identified within the query body by prefixing them with a colon . Here, we've changed the ' ? ' to ': length '. The Session object provides a createQuery() method that gives us back an implementation of the Query interface with which we can work. Query has a full complement of type-safe methods for setting the values of named parameters. Here we are passing in a Time value, so we use setTime() . Even in a simple case like this, the syntax is more natural and readable than the original version of our query. If we had been passing in anonymous arrays of values and types (as would have been necessary with more than one parameter), the improvement would be even more significant. And we've added a layer of compile-time type checking, always a welcome change.

Running this version produces the same output as our original program.

So how do we get the query text out of the Java source? Again, this query is short enough that the need to do so isn't as pressing as usual in real projects, but it's the best way to do things, so let's start practicing! As you may have predicted , the place we can store queries is inside the mapping document. Example 3-9 shows what it looks like (we have to use the somewhat clunky CDATA construct since our query contains characters ”like ' < ' ”that could otherwise confuse the XML parser).

Example 3-9. Our query in the mapping document
 <query name="com.oreilly.hh.tracksNoLongerThan">          <![CDATA[            from com.oreilly.hh.Track as track            where track.playTime <= :length          ]]>       </query> 

Put this just after the closing tag of the class definition in Track.hbm.xml (right before the </hibernate-mapping> line). Then we can revise QueryTest.java one last time, as shown in Example 3-10. Once again, the program produces exactly the same output as the initial version. It's just better organized now, and we're in great shape if we ever want to make the query more complex.

Example 3-10. The final version of our query method
 public static List tracksNoLongerThan(Time length, Session session)           throws HibernateException      {           Query query = session.getNamedQuery(                             "com.oreilly.hh.tracksNoLongerThan");           query.setTime("length", length);           return query.list();      } 

The Query interface has other useful capabilities beyond what we've examined here. You can use it to control how many rows (and which specific rows) you retrieve. If your JDBC driver supports scrollable ResultSets , you can access this capability as well. Check the JavaDoc or the Hibernate reference manual for more details.

3.3.3 What about...

...Avoiding a SQL-like language altogether? Or diving in to HQL and exploring more complex queries? These are both options that are covered later in the book.

Chapter 8 discusses criteria queries, an interesting mechanism that lets you express the constraints on the entities you want, using a natural Java API. This gives you the benefits of compile-time syntax checking, and easy dynamic configuration, all in the language you're already using to code your application. It also supports a form of 'query by example,' where you can supply objects that are similar to the ones you're searching for.

SQL veterans who'd like to see more tricks with HQL can jump to Chapter 9, which explores more of its capabilities and unique features.

For now, we'll continue our examination of mapping by seeing how to represent groups and links between objects.



Hibernate. A Developer's Notebook
Hibernate: A Developers Notebook
ISBN: 0596006969
EAN: 2147483647
Year: 2003
Pages: 65
Authors: James Elliott

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net