Hibernate named queries rock

I’m now working on my second project with Hibernate, having delivered the first, and I’m playing with some of the features I didn’t have time to figure out last time. And I have to say: named queries rock, big time.


Our datamapper layer has one method for loading objects. It takes a query name and a map of properties (for name-value pairs). We create the query by name and then copy the map into the query, like so:

// Exception handling removed for brevity.
public List find(String queryName, Map params) {
  Session session = _sessionFactory.openSession();
  try {
    Query query = session.getNamedQuery(queryName);
    for (Iterator i = params.entrySet().iterator(); i.hasNext(); ) {
    Map.Entry entry = (Map.Entry) i.next();
    query.setParameter((String) entry.getKey(), entry.getValue());
  }
    return query.list();
  } finally {
    session.close();
  }
}

(Another option would have been to pass an object in, and simply pass that in and use JavaBean getters to copy parameter values in. But the map looks easy to set up from the caller’s side)

We then define the queries using XDoclet tags in the domain class, along with all of the other Hibernate tags. This gives us a very nice grouping of the queries, and we can easily see what queries have been written for an object (kind of like EJB finders, but without the compile time linkage). That’s important for indexing the database later.

This just makes whipping out new queries so bloody easy. Define a test for the query, see it fail, define the HQSL, run the test, see it pass, call it in the client (insert suitable tests here), and away you go.

If you use Hibernate, and you’re not using named queries, what are you waiting for?


Updated:

By request, here’s an example. Start with the test.

/** Find accounts by borrower name. */
public void testFindAccountsByBorrowerName() {
  Map parameters = new HashMap();
  parameters.put("borrowerName", TestFixture.ACC_NAME);
  DataMapper mapper = new HibernateDataMapper();
  List results = mapper.find("findAccountByBorrowerName", parameters);
  assertNotNull(results);
  assertFalse(results.isEmpty());
  assertTrue(results.contains(TestFixture.ACCOUNT));
  // TODO: Maybe check the other results to ensure that we haven't brought back any
  // false positives
  }

Client code looks similar; construct a map of parameters somehow, and pass it through.

The XDoclet annotations get a little more interesting. For full details, refer both to the Hibernate manual and the XDoclet manual.

/**
* Holds details about an account.
* @hibernate.class table="ACCOUNT"
* @hibernate.query name="findAccountsByBorrowerName"
* query="select a from accounts a where a.name = :borrowerName"
*/
public class Account {
...
}

Working out the annotations can be tricky sometimes; my normal technique is to either look at one I prepared earlier, or to do the configuration by hand so I know what I’m trying to achieve, then to roll it back to to the XDoclet comments.

Advertisements

Author: Robert Watkins

My name is Robert Watkins. I am a software developer and have been for over 18 years now. I currently work for people, but my opinions here are in no way endorsed by them (which is cool; their opinions aren’t endorsed by me either). My main professional interests are in Java development, using Agile methods, with a historical focus on building web based applications. I’m also a Mac-fan and love my iPhone, which I’m currently learning how to code for. I live and work in Brisbane, Australia, but I grew up in the Northern Territory, and still find Brisbane too cold (after 16 years here). I’m married, with two children and one cat. My politics are socialist in tendency, my religious affiliation is atheist (aka “none of the above”), my attitude is condescending and my moral standing is lying down.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s