Saturday, February 16, 2013

Enums, Hibernate 4 and Oracle database

Recently we were forced to upgrade our application, happily using Hibernate3.5, to latest version of our company's internal framework (must...resist...temptation...to...rant...about...it...). It turned out that this version has a dependency on Hibernate 4.1 so we had to upgrade our persistence layer as well. It's not really a hard job, when you follow the migration guide provided by Hibernate, but after having the project build and pass all the tests (including persistence tests using in-process HSQLDB) again we noticed a strange error at runtime, when it got deployed to app server and run on our target database - Oracle 11. It was happening when a Java enum value was passed into a Criteria query as a parameter:

I browsed the documentation of Hibernate (which is rather helpful most of the time) but couldn't find anything mentioning changes in how one should map enums in entities (we're using XML files not annotations). Our mapping has been untouched for years:

We found the solution when we realized that org.hibernate.type.EnumType has changed quite a lot between Hibernate versions 3.5 and 4.1. Now there's a possibility to specify a useNamed parameter in the mapping (with boolean value) which prevents EnumType from guessing the way to use the enum (ordinal() or name()) in the query. Adding this parameter to the mapping solved our problem.

As always, the one to blame is Oracle. Their driver is not fully compliant with JDBC 3.0 spec even if they say so. This link revealed that this problem is known for years but of course Oracle is like the crazy nastyass honey badger - it doesn't give a shit. This article has also made clear to me that the problem is in the JDBC driver and that I have to look for a workaround. Fortunately, I didn't have to produce yet another custom UserType to make this work.

Good job, Oracle!