-->
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.  [ 6 posts ] 
Author Message
 Post subject: Multiple Sessions - cant reattach
PostPosted: Fri May 04, 2007 6:33 am 
Newbie

Joined: Tue Aug 08, 2006 3:53 am
Posts: 17
Location: Tanznaia
Dear All,

I have a problem reattaching pojos across multiple sessions. These pojos are value objects - like Money or Long - in that their value is more important than the reference. Two separate instances of the pojos are equal if they have the same value... I think the code speaks for itself...

Code:

pojo1 = session1.get(eg.ThisObj, objId);
session1.close();

//..a bit later... open a new session
pojo2 = session2.get(eg.ThisObj, objId);
session2.close();

assertFalse(pojo1==pojo2);
assertTrue(pojo1.equals(pojo2));  //value objects

//-----------  later... --------------

//..open a third session
session3.lock(pojo1, LockMode.NONE);
session3.saveOrUpdate(pojo1);  //is most up-to-date data
//use pojo 1 no problem...

//------ elsewhere in the system -------
// I want to start using pojo2

session3.lock(pojo2, LockMode.NONE);   
//ERROR!! - Throws NonUniqueObjectException



I want to reattach this second pojo before I start using it so that I have the most recent data. This is also necessary for any LazyInitialised Collections held within it. Lock doesn't work because it uses the IdentityMap inside the session during the first half of the process, which doesn't find the existing equivalent pojo already there. Then the second half of the process tries to save the second pojo - only to find the other one sitting in the session and throwing an error.

I can't really use Merge as I can't replace the pojo2 reference (it's held in other objects...) and I can't just use one session as the different steps span web-requests...

Any clues? This problem is causing me significant headaches. I just want a refresh function that fixes references to the persistent session so that my Lazy Initialisation works, and merges any changes in data. This doesn't sound too much to ask for, does it?

How do i do that?

Regards,

Ben.[/code]


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 04, 2007 9:04 am 
Regular
Regular

Joined: Wed Nov 17, 2004 11:49 am
Posts: 65
Location: Pittsburgh
You can:

Code:
session.evict(pojo1); //or pojo2, since they have the same PK
session.lock(pojo2);

//OR
session.merge(pojo2);


Anyway you look at it, Hibernate isn't going to go out through your application and update all the references to this or any other entity that are not managed by this particular session (session3). Hibernate doesn't have any knowledge of detached or transient instances. So, if you want to avoid overwriting a change to this entity, you will have to refresh(pojoX) to get the database contents. Otherwise, you can look at versioning.


Top
 Profile  
 
 Post subject: Merging is not quite enough
PostPosted: Sat May 05, 2007 5:22 pm 
Newbie

Joined: Tue Aug 08, 2006 3:53 am
Posts: 17
Location: Tanznaia
Kerstetter,

Hi there, and thanks for you input. I don't expect Hibernate to locate detached pojos for me and update them, but I would like it to update two copies, or rather clones, of the same pojo (essentially the same, just a different object ref identity) when I ask it to.

Merge is very neary enough, except that it returns the newly merged pojo rather than updating the reference you gave it. This is a problem for me, as the reference will be tucked away in the system, somewhere, probably in multiple places. I just want to to get/set any values that have updated sinse it was originally loaded and to reattach any lazy collections with the new session so that they will work.

Can you help?


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 07, 2007 8:53 am 
Regular
Regular

Joined: Wed Nov 17, 2004 11:49 am
Posts: 65
Location: Pittsburgh
OK, going back to your original code snippet:

Code:
session3.evict(pojo1);
session3.refresh(pojo2);


Top
 Profile  
 
 Post subject: Session as long lived cache, connections refreshed
PostPosted: Mon May 07, 2007 12:42 pm 
Newbie

Joined: Tue Aug 08, 2006 3:53 am
Posts: 17
Location: Tanznaia
Kerstetter,

Thanks for your help with this. I've implemented your suggested eviction/refresh idea in an error handler so that it tries to do a simple lock first, and if there is a problem, it bumps the old version out and refreshes the new one. This should work as a final line of defence but is a bit ugly - I'm worried I'm going to have two versions of the same object floating around that I think are simple references to each other but are actually independant. so I started trying to engineer around the problem.

I won't go into the details, but basically I found myself wanting to keep a cache of all open pojos that persists between cycles (this is a web app so by cycles I mean https request/response cycles). I'm useing the openSessionInView pattern so I can just add some code to the beginning of the new session that reattaches all the cached pojos. This means that next time I load up some objects, it'll reuse the reference that's already there and should avoid the whole problem entirely (although I'm still going to use your nifty evict/refresh pattern as a last resort).

However I started asking myself, "why am I basically wrapping the session up in a cache, when it's already got a cache built in? Oh yeah, because everyone says it's bad to keep a session open because of the database connection. This makes me think that perhaps a 'session' should be split into two objects - one for the cache and one for the 'connection.' Then I wondered if you could do this anyway...

Does anyone know how to reopen a session with a fresh connection?

Thanks,

Ben.


Top
 Profile  
 
 Post subject: session-per-conversation
PostPosted: Tue May 08, 2007 2:36 am 
Newbie

Joined: Tue Aug 08, 2006 3:53 am
Posts: 17
Location: Tanznaia
Kerstetter,

Just to let you know I've had a solution to this problem already. There's another Hibernate pattern called Session-per-conversatio which does exactly what I described - you keep your session open longer and close() just frees up the database conection. When you next use the session it fetches a new connection from the pool and lets you carry on. It's perfect.

I've just got to figure out a way to limit the size of the session cache so I don't crash the server too often - and find a way to make the session threadsafe.

Cheers,

Ben.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 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.