-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 21 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Lazy Initialization across Sessions
PostPosted: Mon Feb 09, 2004 1:05 pm 
Beginner
Beginner

Joined: Tue Jan 27, 2004 6:58 pm
Posts: 20
I've been reading up on some of the topics regarding lazy initialization and I wanted to summarize the topic to see if I have a correct understanding of how lazy initialization works:

Object 'A' (which has a reference to object 'B') is loaded in a session. At that point a Proxy for object 'B' is created and "set" on Object 'A'.

At a future point in the application a request is made for object 'B', and a getter on object 'B' is invoked. This should force the Proxy to attempt to retrieve the actual data for object 'B', right?

I'm assuming that if you let Hibernate create the Proxy objects the standard behavior for those proxies is that the getter/setter methods on the target class are overridden in the proxy sub-class with code that checks to see if the data has been retrieved from persistence (if not the retrieval is performed).

But, if the session that object 'A' was loaded in has since been closed, when you invoke an accessor method on object 'B' you will get an exception.

So here is my question - According to other threads, you can aviod this exception by using the session.lock(Object o, LockMode lm) method - but which object needs to be locked to the new session - is it object 'A' (the object already retrieved), or object 'B' (the proxy-represented object)? I'm assuming it is object 'B', but I am not sure.

If this is the case, what would be an advisable point to insure that the object is "locked" to the new session? My preference would be to make it part of the code in the Proxy itself, but I am not sure I have access to that.

Thanks in advance,

Jonathan House


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2004 2:36 pm 
Beginner
Beginner

Joined: Tue Jan 27, 2004 6:58 pm
Posts: 20
I dug into the code for the proxies (using CGLib) and this is what I have observed. At the point that any method on the proxy is accessed (other than requesting the ID) the intercept method is called on the CGLIBLazyInitializer. If the proxy has not been initialized, the initialize method on LazyInitializer is called, which is where the session check occurs.

Based on this sequence, I don't see a clean place to lock the proxy to a new session if the session that the uninitialized proxy was loaded on has been closed. Am I missing something here? Ideally I would like to change the behavior of the LazyInitializer - so that if the original session is closed I would have a chance to open a new session and lock the proxy to it, rather than simply throwing an exception. Is there any options that I am missing?

Jonathan House


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2004 2:38 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
You will break the transaction semantis of your application if you do that.

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2004 2:48 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
I must not be understanding something here.

If the original session that created the proxy has been closed then, of course, you can lock the proxy in a new session.

What is the problem here?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2004 2:49 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
He wants to do it implicit, not explicit.

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2004 2:54 pm 
Beginner
Beginner

Joined: Tue Jan 27, 2004 6:58 pm
Posts: 20
I realize that the transactional integrity goes away, but I really don't see another option at this point if I want to use lazy instantiation and still use sessions in the way that I have seen recommended in the Hibernate documentation.

It seems reasonable to me that you will have situations where you will load a parent object at one point in a workflow, and then lazily initialize child objects at an separate point. But keeping the session around for that full time seems like a bad idea according to the Hibernate documentation.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2004 2:56 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Thats why you explicitly lock() or update() the child if you need it.

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2004 3:01 pm 
Beginner
Beginner

Joined: Tue Jan 27, 2004 6:58 pm
Posts: 20
No, I'm not asking for Hibernate to do it implicitly. I'm just looking for the best place to put the code that will lock the proxy to a new session so that I don't run afoul of the Lazyinitializer code.

As I stated above, it seems like the best place for my situation would be to modify the initialize method in the LazyInitializer to get a new session if the old one is closed, but I would much rather not touch core Hibernate classes unless I am convinced that there is not another place to get the same result.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2004 3:09 pm 
Beginner
Beginner

Joined: Tue Jan 27, 2004 6:58 pm
Posts: 20
christian wrote:
Thats why you explicitly lock() or update() the child if you need it.


And that is exactly what I want to do, but I only see two ways to do it:

1) Once I have the object returned by Hibernate I can go to the proxy object for each of the lazily initialized objects and create a new session and lock them to it. But the con of this approach is that I am creating a new session regardless of whether the proxy will actually be initialized.

2) Once you access any method on the proxy other than the ID accessor, the intercept method on CGLIBLazyInitializer is called. At this point we know that the proxy needs to be initialized based, so this seems like the best place to create a new session and lock the proxy to it. But I haven't seen a way to hook into it without changing Hibernate code (which I am reluctant to do).


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2004 3:10 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
In other words, you like to make it work automatically, hence implicit if you call a proxied association.

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2004 3:12 pm 
Beginner
Beginner

Joined: Tue Jan 27, 2004 6:58 pm
Posts: 20
Yes, implicit from the perspective of my application, but explicit from the perspective of Hibernate if there is a place where I can hook into.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2004 3:18 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Then your application will have implicit and therefore ad-hoc transaction semantics.

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2004 3:28 pm 
Beginner
Beginner

Joined: Tue Jan 27, 2004 6:58 pm
Posts: 20
That is something that the framework I am building can handle without problems. But my original question remains - is there a way for me to cleanly hook into the proxy initialization process so that I can insure that there is an open session associated with the proxy object?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2004 6:53 pm 
Newbie

Joined: Sun Dec 28, 2003 4:35 pm
Posts: 13
Hy Jonathan,
does your code run on more than one JVM?

Yes?
http://forum.hibernate.org/viewtopic.php?t=926251

No?
Why do you want to close the session, if you think that the "user" of the loaded objects wants to access nonloaded data? Too many connections? Too long transactions?

I am thinking of a servlet container, where for example jsp/jstl are parsing the half-loaded objects, but I think it is more general:

You could open a hb-session at the beginning of a request-response-cycle and close it at the end of the cycle . Instead of caching objects somewhere in the web-session between the requests and using ad hoc hibernate sessions for lazy loading, you can reload the needed objects explicitely and install ehcache which does the "lazy loading" for you.

Salut Thomas


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 11, 2004 6:01 am 
Newbie

Joined: Wed Feb 11, 2004 5:08 am
Posts: 14
Hi all!

We are having the exactly same problem when creating Windows desktop application (Swing UI, POJOs as Domain Objects, DAOs using Hibernate to get persistence for to DOs).

We have a big Test class and in the beginning of the program we would like to list all Tests in the system so that user can open one of them. Of course to get the Tests to the list, there is no need to load all the data from the Test (it would be hundreds of megabytes) but only the name, type etc..

I read the http://www.hibernate.org/41.html and we could propably use this pattern, but at the moment I'd like to look for more general solution. (I'm not yet sure that the listing of Tests would be our only problem spot)

At the moment our DAOs are created in the way Hibernate documentation suggest. (One Session is created in the beginning of the method, and closed when the database transaction is done) Here is the example code:

Code:
   public Set getAllTests() throws DataManagerException {
      try {
         Session session = sessions.openSession();
         Query q = session.createQuery("from domainobjects.Test");
         session.close();

         return new HashSet(q.list());
      } catch (HibernateException e) {
         log.error("Couldn't load all Tests. ", e);
         throw new DataManagerException("Couldn't load all Tests. " + e.getMessage(), e);
      }
   }



Now, when I afterwards try to use lazy collections of the acquired Test object, I, of course, get the LazyInitializationException since Session is closed.

As I see it at the moment (after reading this forum) it seems that we have two possibilities:

1. Reconnect the Test object somehow to a new Session before accessing collections.

2. Keeping the Session open all the time we are using the Test.


Now I'd like to know if anyone has a good design pattern for the first case, since I haven't been able to figure out any nice way to do it. Any ideas?

Another question is for the second option. Hibernate documentation states that Sessions should not be used as a long time object. What are the actual cons of this? Will something be broken if I create one Session when the program starts and use it all the time when the program is running (I could of course flush it etc during its lifespan). Ideas about this?

Or is there some third way to do the thing? :)


Sincerely,

-Jouni Hartikainen


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 21 posts ]  Go to page 1, 2  Next

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.