Posts Tagged ‘hibernate’

Hibernate JPA and Enums

Tuesday, March 17th, 2009

Assume you have a simple enum:

public enum Status {
  ACCEPTED, REJECTED, NOTREADDEN
}

And your legacy database stores it as ordinal values (ACCEPTED = 0, REJECTED = 1, NOTREADDEN = 2). For reasons lost in time, DBA created the column as “varchar”. If you want to use JPA, you will have a bad time using Hibernate:

java.lang.IllegalArgumentException: No enum const class mypkg.Status.1
  java.lang.Enum.valueOf(Enum.java:196)
  org.hibernate.type.EnumType.nullSafeGet(EnumType.java:110)

After digging into EnumType.java, I noticed it is hardcoded “if-varchar-then-name-else-ordinal”. I assume they never dealed with ancient, legacy databases.

If I switch to TopLink, it works as expected… One thumb down to Hibernate…

Changing HSQLDB in-process database default password

Wednesday, June 18th, 2008

HSQLDB is not the kind of database I can use in enterprise systems (with terabytes of data), but it is specially useful if I need a simple RDBMS to small (or temporary) databases.
While trying it with Glassfish, I got a big problem: if you create an in-process database (using “jdbc:hsqldb:mem” or “jdbc:hsqldb:file” or “jdbc:hsqldb:res”), HSQLDB creates a default user named “SA” with an empty password. But Glassfish does not accept data sources without passwords (I get a “No PasswordCredential found”).
To solve this, I grab the HSQLDB sources and changed the org.hsqldb.Database class. The “reopen” method has the following command:

if (isNew) {
  sessionManager.getSysSession().sqlExecuteDirectNoPreChecks(
    "CREATE USER SA PASSWORD \"\" ADMIN");
  logger.synchLogForce()
}

I just changed it to:

if (isNew) {
  sessionManager.getSysSession().sqlExecuteDirectNoPreChecks(
    "CREATE USER " + urlProperties.getProperty("user") +
    " PASSWORD \"" + urlProperties.getProperty("password") +
    "\" ADMIN");
  logger.synchLogForce();
}

Compiling with “ant jar” (in build dir), the new hsqldb.jar will now allow you to create the user based on the credentials passed as login. But this will only work if you compile with a JDK 5, because a lot of methods required by JDBC in JDK 6 are implemented by throwing UnsupportedOperationException.

For some reason, Glassfish and HSQLDB with in-process only works with OpenJPA. I’ve tryed with Hibernate and TopLink, with really strange results. If I find a solution, I’ll post later.

How-(not-)to use Hibernate

Tuesday, April 1st, 2008

Digging into some legacy code, I found the worst way to initialize Hibernate. The first step should be something like:

Configuration cfg = new Configuration();
cfg.addClass(Bean1.class)
   .addClass(Bean2.class)
   .addClass(Bean3.class);

But I found this:

Configuration cfg = new Configuration();
Object[] objs = new Object[] {
    new Bean1(), new Bean2(), new Bean3()
};
for (int i = 0; i < objs.length; i++)
    cfg.addClass(objs[i].getClass());
}

You only need to know the basics of Java to find out the waste of memory and CPU, instantiating a lot of classes (and an array) only to get the class instantiated. And, of course, the unnecessary loop to iterate over the array. It’s like baking a cake to find out the brand of the flour.

As if it’s not enough, this piece of code is replicated in about 7 spots. Yes, the right way to configure Hibernate is using the “HibernateUtils” pattern, as in documentation.

And, as if it’s not enough yet, this piece of code creates a SessionFactory that is sent via constructor to an entire hierarchy of classes. Yes, it is the worst solution, since the Session creation could be on HibernateUtils (as in documentation, again).