Hibernate Resource Management with Callbacks

Hibernate is a popular ORM library that uses abstractions of SQL transactions and other DB concepts. Like anything that deals with resources that must be cleaned up (network sockets, file handles, DB connections, transactions, etc.), ensuring that these resources are cleaned up correctly can get pretty verbose. For details on how to structure resource cleanup code in general, see David M. Lloyd’s article on the subject.

As our use of Hibernate grew beyond a few simple DB interactions, the amount of mostly-duplicated boilerplate code became more and more irritating, so we created some helpers to cut down on the duplication. I suspect other people probably have the same concern, so I’ll show how we were able to simplify our Hibernate interactions (as well as reducing error-prone duplicate code).

Hibernate Basics

The Hibernate class—technically an interface—that typically starts a Hibernate “conversation” is SessionFactory. Most people probably start off with a simple HibernateUtil class just like the one described in the Hibernate tutorial. This is simply a way to easily access a single SessionFactory instance.

This doesn’t do robust error handling, though. In fact, HibernateException can be thrown from every single one of these method calls, though you wouldn’t know it if you put this code in a Java editor — HibernateException extends RuntimeException, so it is unchecked. If tx.commit() threw HibernateException, the session would never be closed. This can cause memory leaks. Here’s a better version of the code with more error handling.

That’s an awful lot of code just to create a row in the DB! However, we can do better. First, move the contents of the finally blocks into their own methods. They can be static methods as they have no state, but you’ll want to have a logger available to record when resources can’t be closed. Here, I use SLF4J‘s Logger interface in a static logger field.

publicstaticvoid tolerantClose(Session session){if(session.isOpen()){try{
session.close();}catch(HibernateException e){
logger.warn("An error occurred while closing the session.", e);}}}publicstaticvoid tolerantDispose(Transaction tx){// we're not in XA/JTA, so wasCommitted should be reliable. See the javadocs.if(!tx.wasCommitted()){try{
tx.rollback();}catch(HibernateException e){
logger.warn("Failed to rollback", e);}}}

Focusing on the real work

Using methods to close sessions and transactions will help, but it’s still quite verbose overall. Pretty much everything that’s done with Hibernate is done in the context of a Session and a Transaction, so what if we hide all the setup and teardown of Session and Transaction and focus on just the work that needs to be done? First, an interface to represent the work to do:

I’m declaring the method to throw DaoException, a simple subclass of Exception. This is because for the way we use Hibernate it makes more sense to have Hibernate interactions throw checked exceptions than to throw unchecked exceptions, but if you like Hibernate’s HibernateException, feel free to remove uses of DaoException.

The session factory is referenced as a field. I recommend creating a class that wraps a SessionFactory and exposes runCallback and other methods without exposing the SessionFactory itself. You may even be able to have HibernateUtil (or equivalent) only expose this wrapper and never expose SessionFactory at all.

The method is generic and has its own T generic parameter. The wrapper class itself need not be generic (and should not be). An example of how this method is used (below) should make this clear.

DbResourceCloser is simply a class containing the methods described above.

That has a much better ratio of work done to code written. (Also, nothing in that code is specific to User; you could use it to save any persistent class. You may wish to put a method that does just that on your version of SessionFactoryWrapper, but note that changes that happen once a Hibernate Session has been closed will not be automatically tracked by Hibernate. This is fine if you have already set up all the data in the persistent class before you save it.) Now that we have this core abstraction done, a lot of other things become simpler. What if you want to use a Work object to do some raw JDBC commands? We can easily add that to the wrapper class:

Now that it’s easy to do raw JDBC operations, let’s further illustrate the convenience of callbacks by making a way to simply operate on every result returned by a prepared statement. First, the callback interface:

This is a Hibernate tutorial, after all, so how about another callback that’s the Hibernate-level equivalent of the prepared statement callback? This one is for easily performing read-only operations on the persistent entities returned from using a Criteria. This is the callback interface:

The cast() method is simply so that delegate() need not deal with casting the Objects returned by Hibernate to the appropriate persistent class. (You could also do it with clever usage of Class#cast().) The usage example below should make it clear how this is used, but first we need the method that runs the callback.

Using these tools, it’s easy to create methods that quickly and safely perform CRUD operations, as well as to execute more sophisticated logic like the criteria-based callback. This is far from the only way to organize Hibernate code, though, so feel free to comment if you have suggestions or improvements.

I mostly use spring template classes which perform the boilerplate you outline above. I assume you are not using Spring or did you make a conscious decision to take this approach as opposed to Spring hibernate templates?

Marshall Pierce

John, thanks for bringing that up; I should have mentioned Spring’s hibernate support. I’m not using Spring IoC, though that isn’t necessarily a reason not to use Spring’s ORM library. There are a couple reasons why I didn’t use Spring ORM:
– We’ve purposely kept our Hibernate usage pretty simple to avoid straying into the bad parts of ORM.
– We don’t (yet) need things like Spring’s declarative transaction management.
– It’s pretty simple to write yourself. :)
– DataAccessException is unchecked which, though fine for many usages, doesn’t work well for our usage. This could, of course, be solved by wrapping with a checked exception as I’ve done here with HibernateException.

Spring ORM is a reasonable option, though, and if JTA support or other fancy things one can accomplish with Spring are needed I would certainly recommend at least trying it out to see if it works for you.

Jeff G

this is called the template pattern from the GoF patterns. I’ve used it for the last decade for all my DAO implementations, hibernate or not. It does remove a ton of boilerplate code, but junior developers tend to get lost in the template. Say they have an error in a query, their debugger will pull them through the methods of the base class. They’ll learn to use it over time, but their is a learning curve.

JEE 5 and 6 make templating even easier with generics. My JEE version is like this