Reputation: 7083
I have a domain object that has an attribute which is a collection containing another domain object. This is accomplished using a hibernate mapping (which eventually performs a join on another table). Hibernate, by default, seems to lazily instantiate this collection. This turns out to be a great thing because, depending upon what I need displayed, I do not always need the collection to be loaded.
My issue is the following: when writing my hibernate queries (in my DAOs), I use the following to open / close a Session:
Session session = getSessionFactory().openSession();
//query goes here using the session var
session.close();
The problem is: when Hibernate finally comes around to lazily loading my collection, the Session
has long been closed! How can I get around this? I assume that I have to close the session as I am doing...
This is the error I get:
SEVERE: failed to lazily initialize a collection of ...
Upvotes: 0
Views: 1878
Reputation: 116256
I understand that you open and close the session for each DAO operation. You could instead use one and the same session by all DAOs, opened sometime during intialization and closed at shutdown. Note that the Hibernate Reference mentions "session per operation" as an antipattern:
"Do not use the session-per-operation antipattern: do not open and close a Session for every simple database call in a single thread."
In brief, a session should enclose a unit of work. This may be a single user request (possibly including multiple queries), or a longer conversation (including multiple screens with their own (groups of) queries). In the latter case there is reason to think about not keeping the session ( = transaction) open for extended periods of user think time, but yours does not sound like this case to me.
If you close the session, your domain object becomes detached. You could open a new session, tie your object to it then load the collection, but to me it looks quite a hassle.
Upvotes: 2
Reputation: 403441
If this is occurring within a webapp, then the easy fix for this is to use an OpenSessionInViewInterceptor or OpenSessionInViewFilter. These delay the closing of the session until the whole request has completed, allowing you to navigate lazy associations when rendering the view.
A more general solution is to rewrite your queries so that they explicitly specify which associations should be fetched up-front. This lets you keep the associations lazy by default, while at the same time catering for special cases where you want them fetched eagerly. See the description of "fetch joins" in the Hibernate docs.
A "fetch" join allows associations or collections of values to be initialized along with their parent objects using a single select. This is particularly useful in the case of a collection. It effectively overrides the outer join and lazy declarations of the mapping file for associations and collections
Upvotes: 5