Hmm, how many times have I seen this while learning how to use Hibernate? Too many.
When you load an object defined with an Object-Relational (O/R) mapping in Hibernate, eg. you run a SELECT in your HQL, hibernate retrieves that object but does not, by default, load the whole object graph of any associated objects ie. any other entities you have mapped as being referenced by the object you are loading. This default behaviour is referred to as Lazy loading or Lazy Initialization. What the object you load does have is a reference to a proxy object that can then be used to load the full associated entity when you try and navigate the association in your application code. Hibernate attempts to do this seamlessly for you, but, to be successful, it requires a Session to open the connection to your database and most of the time, depending of course on how you are using Hibernate, the Session object has been closed.
As an aside – the reason we generally open the Session object as late as possible in our data access code, and close it early, is for performance – other threads may be waiting to use it, and its expensive to keep.
When Hibernate attempts to call on the proxy object to obtain our associated entity or collection, and the Session is closed, it throws an LazyInitializationException. Basically, Hibernate is saying “I see you are ready to use that associated object now but I don’t have a full instance of it loaded in memory and I cant go and fetch it from the database for you now since there is no open Session“.
How to Deal With LazyInitializationException?
Well it turns out that there are several ways to deal with it, namely either managing the session in some way or not using lazy loading. One option we have is to turn off the default lazy-loading behaviour for all associations in our mapping:
The problem with this is that if we turn off lazy loading for all our entities then hibernate loads the whole object graph into memory for each query which is obviously not ideal and explains why the default behaviour is to use Lazy loading of associated entities and collections.
There are several approaches to handling the session more effectively, namely Open Session in View, however these too have their drawbacks.
Another approach is to just turn off lazy initialization for the specific associations we are trying to access in our code. For example, I have a User entity in my database schema that references a Domain object. By default this association is lazily loaded, but I can use the ‘lazy’ attribute of the many-to-0ne element to specify that I wish to load the associated object at SELECT time.
<many-to-one name=”domain” class=”com.mypackage.Domain” lazy=”false”>
In the above, when I obtain a User from persistence, the Domain object will now be fully loaded into memory so that I can navigate to it via my User outside of the Session without fear of Hibernate throwing the LazyInitializationException.