Joshua Davis wrote:
-----Original Message-----
From: Richard Wallace [mailto:[EMAIL PROTECTED]
Sent: Wednesday, August 31, 2005 2:38 PM
To: MyFaces Discussion
Subject: Re: JSF + Spring + Hibernate
I do use OpenSessionInView for lazily loading objects in the
same request. The problem that I've been running into is
when objects loaded from Hibernate have lazily loaded
collections and are put into the session before the
collection gets used. Then on a future request, Hibernate
tries to lazily load the objects and can't because the
session used to retrieved them has been closed.
The scope of the Hibernate session must match the scope of any lazily loaded
objects or collections. That's one of the rules of Hibernate (or any other
ORM that I've used, for that matter). Putting a proxy object in web session
scope while the Hibernate session is in request scope breaks that rule. You
need to either use a transfer object, or cause Hibernate to initialize the
proxy by either setting the lazy attribute to false, or using
Hibernate.initialize(). You can also re-associate the object with the
Hibernate session as was mentioned before.
[EMAIL PROTECTED]
I think you may have skipped the rest of my email. I detailed the ways
I'm working around that. I understand it breaks the Hibernate contract,
I was merely mentioning it as a possible issue because everyone had
simply been talking about problems within a single request. I just
wanted to point out that that is not the only issue with lazily loaded
objects and you need to be careful about putting them in the HTTP session.
What do you mean by "use a transfer object?" That's the first time I've
ever heard anyone mention that. The problem with telling Hibernate to
initialize the object graph is that, in most cases I think, the use of
Hibernate is abstracted away from the webapp layer. So your backing
beans don't really know they need to do that and even if they did they
couldn't. And setting the lazy attribute to false is a workaround, but
could lead to large graphs being loaded into many users HTTP sessions.
Reassociating the object with the session has a similar problem as
trying to initialize the object from within the webapp layer before
putting it in the session. Your webapp simply does not know that you
are using Hibernate. And even if it did, it has no access to the actual
Hibernate session.
I toyed around at one time with the idea of trying to create a servlet
filter that would automatically reassociate anything in the HTTP session
with the Hibernate session. There are a couple of problems with that
tho. First off, it's not always easy to determine what objects are
Hibernate persisted objects and which aren't. Second, if the actual
Hibernate object is wrapped in a backing bean that is actually put in
the HTTP session simply scanning objects in the HTTP session won't
work. Finally, what convinced me it was a bad idea is that the only
ways to reassociate an object with a Hibernate session that I was able
to find is to use merge(), update(), or lock(). The first two will
update the database with the object you provide, and locking requires
the underlying data in the db hasn't changed. So you'd lose any changes
that could have occured while the object was in the session.
So, like I said, just refetching the Hibernate objects for each request
is much easier and doesn't cause too much extra load on the database if
your using the 2nd level cache.
Rich