Wednesday, 19 November 2008

Hibernate's Lazy Loading Quirks

I have come across two problems which have caused me no end of grief which turned out to be pretty simple.

LazyInitializationException
When using the Spring OpenSessionInViewFilter, I refer to lazily initialised properties (mapped as many-to-one or one-to-one) in the JSP pages. However I was getting a scenario where if a user performed a certain action I would get the following error:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
After a lot of debugging and sifting through hibernate's source I traced it to a bit of code I had used that someone had posted for having a paged interval collection for hibernate (as oracle doesn't support server side paging). The culprit line of code was:
hibernateTemplate.clear();

//which is defined in Spring's wrapper as
public void clear() throws DataAccessException {
executeWithNativeSession(new HibernateCallback() {
public Object doInHibernate(Session session) {
session.clear();
return null;
}
});
}
This causes all objects that had been loaded previously by that session to be DISCONNECTED from the session. Hence the slightly misleading message. The session is still open, its just longer associated with it.

many-to-one relationships not being lazy

I had a problem with relationships which I had defined as being lazy not being lazily loaded which I only discovered after I turned of the second level cache off. With the cache on, I never saw the requests it made internally to load an entire child-parent-etc hierarchy (which is one bonus of using a cache).
After spending what seemed like hours, sifting through the documentation on lazy loading, fiddling with settings, checking the bytecode libraries, I finally discovered the cause. To get around cases where the 'static' data that these entities were referring to were missing due to some muppet bodging the data, I had set attribute not-found="ignore". This prevents the JSP page blowing up when you try and access the property when all you really want is to display a blank field or maybe a message. However, in order for a relational property to be lazy loaded it must be set to not-found="exception" (which is the default). Its a trade off between dealing with the exceptions where you don't expect them and the performance hit.

1 comment:

  1. This comment has been removed by a blog administrator.

    ReplyDelete