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.  [ 3 posts ] 
Author Message
 Post subject: Escaping NonUniqueObjectException hell
PostPosted: Wed Nov 07, 2007 8:09 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
Hibernate version: 1.2.0.GA

I have the following situation:

1. My application needs to frequently and quickly access a large dictionary of entities, and access child entities 4 levels deep off of each one. There are currently about 400 top-level entities, each having 5-10 children/grandchildren/etc. The number of top-level entities will soon be increasing to 1000 or more.

2. There is no good way to predict which dictionary entries will get frequent access.

3. The entries are rarely updated.

What I've done is query the entities to go into the dictionary at application startup, but don't initialize all their children, grandchildren, etc. Then during normal usage of the application, I reattach the entry and its children, grandchildren, etc. as needed to allow for lazy loading.

The problem is that some of the children/grandchildren/etc of the top-level entries access some very general entities that are commonly accessed elsewhere, and often enough, these other entities are already in the NHibernate session by the time I try to reattach entities from my static dictionary. I end up in NonUniqueObjectException hell.

I can only think of two ways to solve the problem:

1. Every time a new NHibernate session is created, immediately attach every reachable entity (being careful not to lazy-initialize proxied collections) in my static dictionary. Since this will be anywhere from about 500 to 10000+ entities, and the majority of sessions will not query any of those entity types, this would be a horrendously non-performant.

2. Every time NHibernate checks a session cache for an entity, somehow hookup to that operation, and provide it with the matching entity from my static dictionary of detached entities where available.

I'd like to try idea #2, but the operation of checking the session cache doesn't look like something I can hook into. At first I thought I could prevent NonUniqueObjectException by having IInterceptor.Instantiate keep a dictionary of WeakReferences (keyed by a combination of full type name and entity ID) to every entity ever created, pruning dead weak references periodically, but IInterceptor.Instantiate doesn't get called on proxies until the proxy is initialized. I guess if I did that plus add code into every entity's constructor to detect when it's a proxy, and through some awkard service interface have it register itself with my interceptor's otherwise-private WeakReference dictionary, but is there an easier way?

Does anyone else have to deal with the detached objects pattern and run into NonUniqueObjectException from low-level code where the recommendation to "just reattach everything you might need to touch before querying anything in the session" is just not possible?


Top
 Profile  
 
 Post subject: may not be exactly the same situation but
PostPosted: Thu Nov 08, 2007 5:11 pm 
Beginner
Beginner

Joined: Fri Jul 14, 2006 1:51 pm
Posts: 27
Here's what I do. I have a type with a lazily loaded collection and the type is stored in a cache that is not managed by NHibernate. At some point that collection can be accessed and session the type was initially loaded in is long gone. This works for me (the call to NHibernateContext is just getting the current active session or opening a new one):

Code:
if ( !NHibernateUtil.IsInitialized( this.MyCollection) )
                NHibernateContext.GetSession().Lock( this, NHibernate.LockMode.None );


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 08, 2007 6:04 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
Thanks for the reply, but I'm already doing that ...


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