Well, this may turn a number of you off and make you think I’m some sort of Luddite or something, but I have come to a considered opinion:  I don’t really like Hibernate.

Before you consider me an ignorant fool, here are some of my reasons for you to consider (and I may add to this list over time):

1. Performance

Ok, to be fair, the problem isn’t so much Hibernate’s performance.  Hibernate’s performance itself is pretty damn good.  To be intellectually honest, performance problems in Hibernate really come from programmer laziness.

As an example, consider a database with Members, and members have multiple addresses, each of which has some type indicator (one of which indicates the Home address).  Now suppose you want a specific member’s home zip code and you know their primary key.

In the Hibernate world, the natural thing for Joe Programmer to do is to first go fetch the member by id, then iterate through their collection of Addresses looking for the one with the Home indicator, and get the zip code.  After all, that’s the natural thing to do with POJO’s.

However, behind the scenes, Hibernate doesn’t just go straight for the zip code.  First the Member record and all the mapped columns in that row are fetched and loaded into the member object that you don’t really need.  Then, upon referencing the address collection, Hibernate fetches all the member’s Addresses (with all the unneeded columns and not just zip code) from the database, then Joe looks for it in code rather than in the database.

I hear you saying, “well duh, if you write it that way, of course you’ll get extra unneeded database activity.  It’s your own fault.”  And you’d be right.  My argument is that Hibernate, by its very nature, leads you to do it this way.  Hibernate simply can’t know which fields in a persistent object graph you are interested in before you start, so it has to do its database work by “brute force”.  If you want or need intelligence in the database access, you need to build it into your mappings, by having multiple objects mapped to the same tables, or by writing lots of HQL.  And if you’re going to do all that, you might as well access the database yourself directly.

2. Translucent object persistence, not transparent

One of the goals of Hibernate is to make object persistence transparent.  Technically, all this means is that you can take an existing POJO, add mappings in an external file, and voila, it’s now persistent. And Hibernate does that.

In the real world, however, you are never able to take your eye off your persistent objects.  You are always (and always need to be) keenly aware of which of your objects are persistent and which ones are not, how they are mapped, and how your app is connecting to the database.  If you are a Hibernate user and disagree, ask yourself these questions:

  1. Do you write HQL?  If so, you are only writing it for persistent objects and you either know which ones they are, or your code doesn’t work.  And exactly how is writing HQL any more transparent than writing SQL?
  2. Do you find yourself frequently referring to your .hbm.xml files after they are written, to see how things are mapped?
  3. Do you have to do stuff– things like putting your Sessions in a ThreadLocal, or implementing servlet filters — to make sure your Hibernate Sessions stay active when accessed later to avoid exceptions?
  4. Do you echo Hibernate’s SQL to your logs so you can tell what the hell Hibernate is really doing?
  5. Do you have code somewhere in your app that calls getConnection() from a Hibernate Session because you wanted to do something Hibernate couldn’t do easily?
  6. Do you use Hibernate annotations instead of the mapping files?  If so, you definitely aren’t transparently persisting your objects, you’re effectively hard-coding it by annotation.

3. Database activity is too important to ignore

Who out there really believes that database activity should be transparent in the first place? I wouldn’t want most developers I have worked with doing anything in the database without it being a deliberate, conscious act.  (Some of them I don’t want in the database at all, but that’s a different story).

4. I question whether it really saves time in the long run.

When you add up all the time you spend setting up and tweaking mapping files, getting them packaged correctly in your app, dealing with Hibernate session management through some SessionFactory class, avoiding serialization of persistent objects across classloaders, writing HQL instead of SQL, and mentally reverse-engineering your mapping files from the SQL that Hibernate actually generates (”I didn’t want that!  What do I need in my XML file to get the SQL I want?”), I wonder if time really gets saved — particularly in comparison to good old DAO/DTO classes.

I am not saying Hibernate is a bad tool.  It’s an extremely powerful tool, and does a lot of cool things (I particularly like the database dialect hiding)  But while code and business requirements should dictate tool selection, once it’s stitched in, the tool inherently constrains your code and naturally guides it down paths that may not always be so great.  One should select with great, great caution.  (See Ted Neward’s outstanding blog entry, “The Vietnam of Computer Science“)

Leave a Reply