-->
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.  [ 13 posts ] 
Author Message
 Post subject: Re-attach transient objects to session
PostPosted: Wed Feb 27, 2008 4:47 am 
Senior
Senior

Joined: Sat Sep 03, 2005 12:54 am
Posts: 139
Hi,

I have a child collection that is populated dynamically based on user input in the UI but not persisted to the DB until the user requests a save. So, instead of saving to the DB, the transient collection is stored in the cache and regenerated as required.

The reason for this is that repeated user input on the UI forces this collection to be updated frequently and having it persisted in the DB all the time kills performance.

The child objects have a rich connection to other domain objects and which have lazy loading enabled in places and I am getting a LazyInitializationException when I attempt to navigate a collection that has not been loaded yet.

Is it possible to reconnect the collection to a current session so that lazy loading will work?

Thanks,

Jason


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 27, 2008 6:06 am 
Beginner
Beginner

Joined: Thu Nov 29, 2007 4:36 am
Posts: 20
Yes,
you can try : session.Lock(entity,LockMode.None);
then the entity's collections/subentities should load.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 27, 2008 6:19 am 
Senior
Senior

Joined: Sat Sep 03, 2005 12:54 am
Posts: 139
I tried that but it throws an exception because the objects are transient.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 27, 2008 7:31 am 
Senior
Senior

Joined: Sat May 14, 2005 8:40 am
Posts: 130
The cascade settings determine if any related objects are also reconnected. I think you'll need cascade="all" for automatic reconnecting. If you can't work with this cascade setting, you'll have to reconnect the object graph manually. Not nice, but it can be done.

_________________
Cuyahoga


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 27, 2008 7:34 am 
Senior
Senior

Joined: Sat Sep 03, 2005 12:54 am
Posts: 139
I could probably use cascade="all" and then just clear the collection before I save the parent.

How would I go about manually reconnecting the graph? Also, is this something that I should even be considering or is it bad NH practice?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 28, 2008 6:55 am 
Senior
Senior

Joined: Sat May 14, 2005 8:40 am
Posts: 130
jason.hill wrote:
How would I go about manually reconnecting the graph? Also, is this something that I should even be considering or is it bad NH practice?


Dunno, at the time we didn't yet use the NH second level cache in Cuyahoga, we manually reconnected the cached object graph on each request and that worked out pretty well. At least, the performance was top notch. Still, it felt a little bit dirty because quite some infrastructure code was leaking into the app.

_________________
Cuyahoga


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 28, 2008 5:23 pm 
Senior
Senior

Joined: Sat Sep 03, 2005 12:54 am
Posts: 139
Just to clarify - do I manually reconnect the graph using the Lock() method?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 29, 2008 12:29 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
While going through your object graph, you'll have to know yourself if the each detached entity is transient or persistent, and if persistent, if it was changed or not while detached. Then you'll have to do the following:

* If transient, call session.Save()
* If persistent and not changed while detached, call session.Lock()
* If persistent and changed while detached, call session.Update()

Still, if a persistent entity was not changed while detached but one of its collection properties had items added or removed while detached, you'll still need to call Update() rather than Lock().

Doing all this manually is a major pain, but I don't know of any other way if you don't have everything cascading ...


Top
 Profile  
 
 Post subject:
PostPosted: Sat Mar 01, 2008 7:48 pm 
Senior
Senior

Joined: Sat Sep 03, 2005 12:54 am
Posts: 139
Excellent...thanks.


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 16, 2008 6:19 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
For reasons I won't go into here, we recently had to change our cascade policy from "all" to just "delete". Now collections apparently aren't getting reattached when we call session.Lock(entity) on an uninitialized proxy (or an entity with an uninitialized collection)

How do you manually reattach collections if you can't use cascade="all"? Why does the cascade setting even matter here?

In WrapVisitor.cs, I see this code in ProcessCollection():

Code:
IPersistentCollection coll = collection as IPersistentCollection;
if (coll.SetCurrentSession(Session))
{
    Session.ReattachCollection(coll, coll.CollectionSnapshot);
}

Is this what we have to do? Seems awkward, having to hook up both ways, and more verbose than necessary ...


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 16, 2008 6:49 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
Nevermind. I had also just tried changing my calls to session.Lock() to session.Refresh(), but it looks like Refresh() doesn't actually reattach, so we need to lock first and then refresh.

In any case, although the collection attachment methods I pointed out above are public, they are effectively internal since you need to pass the session as the implementation type, not the interface type.


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 20, 2008 5:40 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
Actually, I am getting
Code:
HibernateException: collection is not associated with any session

when I try to initialize an uninitialized collection after reattaching its (already initialized) owner via
Code:
session.Lock(owner, LockMode.None)


From what I understand, this should not happen once the owner is reattached to a session. What am I doing wrong?


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 21, 2008 2:51 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
Aaaargh, it turned out I was trying to initialize an old copy of the collection that I had grabbed before calling session.Lock() and session.Refresh() on the collection owner. The collection instance itself is reassigned to the owner by Refresh(), so I have to make sure I get the collection instance after calling Refresh() on the owner ... (sigh)


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 13 posts ] 

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.