-->
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.  [ 9 posts ] 
Author Message
 Post subject: How to determine if an object is associated with a session
PostPosted: Wed Apr 06, 2005 9:51 am 
Newbie

Joined: Thu Oct 21, 2004 3:03 pm
Posts: 13
Hibernate version: 3.0 Final

Is there a way I can determine if a particular object is already associated with an open session? I'm using Spring's OSIV filter with singleSession="true", which works pretty well in my environment except for the occasional NonUniqueObjectException. I have created a utility service to attach or evict (on demand) a particular object, but I would like my attach method (actually does a getHibernateTemplate().lock(object, LockMode.NONE)) to be able to determine before the exception is thrown if a "different object with the same identifier value" is already associated with the session, and to handle it appropriately if so.

I've tried using getHibernateTemplate().contains(object) before doing the lock, but I suppose it doesn't find the duplicate since this exact object instance is not in the session and it doesn't locate another object instance having the same identifier.

Thanks.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 07, 2005 10:36 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
check you equals hashcode implementation

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 08, 2005 9:41 am 
Newbie

Joined: Thu Oct 21, 2004 3:03 pm
Posts: 13
The object in question has a simple, autoassigned unique id key, and therefore I have no custom equals or hashcode implementation here.

Hibernate is seeing the duplicate object, and the exception thrown references the correct ID by value, so Hibernate has some mechanism for locating duplicates in the session.

Is there a way I can do the same thing, to help detect this situation in my code without waiting for Hibernate to complain?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 08, 2005 10:19 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
session.contains()

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 08, 2005 11:33 am 
Newbie

Joined: Thu Oct 21, 2004 3:03 pm
Posts: 13
I started out by doing getHibernateTemplate().contains(), but it never seemed to work reliably. getSession().contains() is working better for some reason (although that doesn't really make sense). Maybe I was using singleSession="false", or maybe there is a Spring bug somewhere.

Thanks.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 08, 2005 3:47 pm 
Newbie

Joined: Thu Oct 21, 2004 3:03 pm
Posts: 13
Actually I spoke too soon.

Relying on session.contains() is not a good idea, since it is not consistent with the check for uniqueness by key.

Session.contains() invokes PersistenceContext.isEntryFor(Object object), which does a lookup into the entityEntries Map. My object instance does not exist there, so contains() returns false, even though another instance of the object with the same key does in fact exist in the session.

Lock() invokes PersistenceContext.checkUniqueness(), which invokes getEntity(), which does a lookup into the entitiesByKey Map. The object is found there, which results in a thrown NonUniqueObjectException.

There is another method of PersistenceContext called "containsEntity". Shouldn't Session.contains() call PersistenceContext.containsEntity() rather than PersistenceContext.isEntryFor()?

I would consider this to be a Hibernate bug, or at least a misleading implementation. Is there a workaround for this?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 28, 2005 11:33 am 
Pro
Pro

Joined: Mon Sep 08, 2003 4:30 pm
Posts: 203
thomasalva wrote:
Actually I spoke too soon.

Relying on session.contains() is not a good idea, since it is not consistent with the check for uniqueness by key.

Session.contains() invokes PersistenceContext.isEntryFor(Object object), which does a lookup into the entityEntries Map. My object instance does not exist there, so contains() returns false, even though another instance of the object with the same key does in fact exist in the session.

Lock() invokes PersistenceContext.checkUniqueness(), which invokes getEntity(), which does a lookup into the entitiesByKey Map. The object is found there, which results in a thrown NonUniqueObjectException.

There is another method of PersistenceContext called "containsEntity". Shouldn't Session.contains() call PersistenceContext.containsEntity() rather than PersistenceContext.isEntryFor()?

I would consider this to be a Hibernate bug, or at least a misleading implementation. Is there a workaround for this?


No. Unfortunately this is just one of the *big* problems in Hibernate espacially when dealing with complex object graphs.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 27, 2005 6:21 pm 
Senior
Senior

Joined: Tue Mar 02, 2004 6:17 pm
Posts: 151
Switching from Session.load() to Session.get() fixed this problem for now. If this helps you, please credit my post :)

Thanks,
Gili


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 28, 2005 5:07 pm 
Senior
Senior

Joined: Tue Mar 02, 2004 6:17 pm
Posts: 151
My last comment was nonsense, please ignore it.

Here is a simple test-case for reproducing this problem.

Code:
    // Get a theme
    Theme theme = DefaultTheme.getRoot(session);
   
    // Get a child theme
    Theme childTheme = (Theme) theme.getChildren().iterator().next();
   
    // Evict it
    Serializable id = session.getIdentifier(childTheme);
    session.evict(childTheme);
   
    // Reload the child
    childTheme = (Theme) session.get(childTheme.getClass(), id);
   
    // This throws: "org.hibernate.NonUniqueObjectException: a different object
    // with the same identifier value was already associated with the session"
    // because the parent is still pointing to the old child. At flushing time,
    // it cascades saveOrUpdate() on the old child but the session already has
    // the new child (with the same id) associated with the session.
    session.flush();


Now, in-so-far as I see it this is something that should be fixed inside Hibernate. Either evict() should uninitialize references to evicted objects inside associations or -- probably easier -- Session.get() should be modified to reuse these preexisting detached instances.

With the current implementation it doesn't look like there is any reasonable workaround for users to use. It is completely possible that code in one place will evict() while completely unrelated code in another place will Session.get(). Session.contains() will not help here either.

Is there another API or workaround I am overlooking? I welcome your feedback.

Gili


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