02 March 2010

Hibernate : "failed to lazily initialize a collection", Reasons and Solutions

Al Salamo Alykom

Most of us usually focuses the most famous hibernate problem "failed to lazily initialize a collection", So here I'll try to say Why it appears and How to solve.

First Why it appears, When you map a one-to-many relation ship, the default load mode is lazy loading, and this is the best choice thing because Hibernate will not gonna load a collection of objects in memory until you use them.
So, If you try to access this collection within the same session you get the parent object, it will works fine.

So the problem happens when you try to access a collection of some object outside the initiating session.

Second, How to solve.
Hibernates uses proxies to refer to collections (and objects as well) when returned as reference to another object.
Suppose we have tow objects, Country and Region, each Region can contain many countries, So the following code will return an exception:

......
session.beginTransaction();
Region region = (Region) session.get(Region.class, 1);
session.getTransaction().commit();
session.close();
printCountryList(region.getCountries()); // << The problem will happen here

So, Should I keep the session opened across client requests, or what should I do?

There are two solutions and I tried both and both works for me.
Hibernate team says that whevener you accessed any method on the proxy, we will load the (real) object (collection ) for you.
So, In case of the previous example, all you have to do is to call any method on the collection within the session, say size():

......
session.beginTransaction();
Region region = (Region) session.get(Region.class, 1);
region.getCountries().size(); // will make hibernate initialize the collection for you instead of the proxy
session.getTransaction().commit();
session.close();
printCountryList(region.getCountries()); // << Will works very fine

Or you can use Hibernate.initialize() to initialize the collection from the proxy :

session.beginTransaction();
Region region = (Region) session.get(Region.class, 1);
Hibernate.initialize(region.getCountries()); // will make hibernate initialize the collection for you instead of the proxy
session.getTransaction().commit();
session.close();
printCountryList(region.getCountries()); // << Will works very fine


That's all, please if you have such the problem, try any of these ways and tell me know about your feedback.
Thanks.
Post a Comment