Tuesday, April 16, 2013

Hibernate 4 Still Maturing a Year Later?

In December 2011, the Hibernate team announced the release of Hibernate 4.0.Final. A year and a third later, it seems like Hibernate 4.x is still not as mature as I would have liked it to be on launch, let alone with all this extra time to add finesse. This makes me question the viability of the 4.0 line whether or not there are deeper problems with the project and team that are visible on the surface.

Project Background
A client of mine has a project that is now almost four years in development (over multiple releases, of course), and that started with Hibernate 3.3.x, which was current at the time.

During a number of those releases, the project team considered updates on various dependencies, including Hibernate, but hadn't found a compelling reason to upgrade. Since any upgrade introduces some change and risk, this project has continued to use 3.3.x.

A bug filed against that project recently showed that Hibernate's handling of character database columns (e.g. CHAR(10)) was somewhat flawed. This defect is fixed in Hibernate 3.6.8 and Hibernate 4.0.0.CR5, so it was time to evaluate Hibernate for an upgrade.

Evaluating Hibernate 4.x
Since Hibernate 4.x had been out for over a year, it seemed like it was probably worth serious consideration as the target version for the upgrade. I discarded 4.2.0.Final because it was relatively recent, and did a trial upgrade to 4.1.11.Final. The 4.1 line has been around since early February 2012, so it is also more than a year old.

There were immediately some issues, which I expected -- APIs have changed, deprecated methods removed, and so forth. This is pretty normal for an upgrade. But over the course of solving those problems, I got the strong impression that Hibernate 4.x still hasn't matured. After fighting with that for a while, I eventually decided that I would drop down to 3.6.10.Final, which is where I left it.

JDBC Connection and Work API
One of the first stumbling blocks was the removal of the deprecated method to get the JDBC connection underlying the Hibernate session. There are a few places where this project interacts directly with JDBC, because it's the best fit for that particular situation, and rather than having two mechanisms for accessing the database, we borrow Hibernate's JDBC connection to do a little bit of work.

Hibernate has allowed you to access the underlying JDBC connection for a long time, but in Hibernate 3.3.0 (I believe), this methods was deprecated and a new API where a connection is passed into a custom class implementing org.hibernate.jdbc.Work was introduced. This allows Hibernate to manage the JDBC connection more directly, which seems like a sensible idea.

In Hibernate 4.x, the deprecated Session.connection() method was removed. I'm in favour of removing deprecated methods, so this didn't bother me, and I set about modifying the project code to factor this in. It added some awkward indirection in our existing approaches, but I could see that a more involved refactoring might make that less awkward.

However, I also discovered that the Work API isn't covered in the Hibernate documentation (it's only even mentioned once that I can find), which still refers to Session.connection (e.g. Developer Guide, Reference Documentation), which has already been removed.

When Hibernate 4.x was first released, referring to methods that have been removed in the documentation would have just been an oversight. Over a year later, it seems clear that this isn't something that's just about to be fixed.

Bootstrapping Hibernate
For the longest time, bootstrapping Hibernate went a little like this:


Hibernate 4.x involved a significant change the plumbing of Hibernate. The release notes mention both "Clean up of Session opening from SessionFactory" and "Introduction of ServiceRegistry". In the process, they deprecated buildSessionFactory() in favour of buildSessionFactory(ServiceRegistry). Wanting to better understand this change and learn the proper replacement for the above stanza, I went to the documentation.

Unfortunately, here's another case where the documentation is out-of-date, continuing to refer to now-deprecated initialization approach: Getting Started, Reference Manual. In looking at the source code comments for Configuration, I found references to Jira issues talking about deprecation (and that Configuration would be removed in Hibernate 5.0): HHH-6183, HHH-2578 and HHH-6586. Reading these and some related issues implies that the hibernate team:

Given that this change seems like a big part of what's included in 4.x, and given that it's a bit of mess, and doesn't seem to have gotten significantly less messy in the year and four months since 4.0's release, I decided that upgrading to Hibernate 4.x was not only unnecessary, but possibly a dangerously bad idea.

What's the Problem?
So, what's the problem, Hibernate team? Why is your documentation not up to date with your latest major release? Why are there significant revisions that seem a little half-baked? Why haven't these problems improved in the 4.1 release and all of its patches? Is there a more fundamental dysfunction that's causing all of these surface-visible problems?


  1. HI - I am planning to upgrade our application's hibernate version from the 3.6.4 to 4.1.12 or 3.6.10. Please share your thoughts

  2. I haven't tried again with 4.2 or 4.3; it looks like things have continued to improve somewhat, although it does feel to me like the fundamental problems are still there.

    3.6.10 is probably a pretty easy transition which will probably fix bugs and introduce almost no change to your system. It also seems like the Hibernate team have continued to make important bug fixes to 3.6, which is great. On the other hand, it's dated, API-wise, and if you want to eventually move past that version, you might be deferring pain into a future upgrade by not going up to 4.x now.

    It might be worth spiking on a 4.x release to see how it pans out for you. If it goes smoothly, go with it; if it turns out to be troublesome, drop back to 3.6.10, which will probably be fairly painless.