Hello All,

I found that usage of database identity in Java produces quite interesting problem in 
OJB:

In my application all persistent Java objects use database identity instead of Java 
reference identity (i.e. Persistable.equals() is
redefined so that two persistent objects are the same if they have the same primary 
key and top-level class).

In OJB, for each field declared in repository there is dedicated instance of 
AnonymousPersistentField that stores
object-to-field-value mapping in WeakHashMap (in fkCache attribute).

Despite usage of cache (ObjectCachePerBrokerImpl in my case) it is possible that 
identical DB objects will end up as different Java
objects during retrieval of complex objects.

Now imagine what happens when two identical instances are retrieved:

1). When first instance is retrieved it stores its foreign keys in 
AnonymousPersistentField.fkCache under instance's identity.
(happens in RowReaderDefaultImpl.buildWithReflection())

2) When second object is retrieved and stored in fkCache, first instance is probably 
still cached [WeakHashMap entries are cleaned
up only during GC]. Since keys are identical WeakHashMap only updates entry value and 
DOES NOT update entry key.

3) If Full GC happens after that moment it will dispose fcCache entry if the FIRST 
reference becomes soft-referenced only.

Can you please comment on this issue?

BTW From OJB client side it looks like loaded objects randomly appear without their 
childen. Spooky :-)

May be the real problem is duplicate instances of the same objects?

All the Best,
Andy

p.s. An additional thing - will it be possible to add fast assertion into 
ReferencePrefetcher.associateBatched() that will verify
that all parent objects found their children in case of non-null FK?

CollectionPrefetcher, line 117:

+          boolean childFound = false;
            for (Iterator it2 = children.iterator(); it2.hasNext(); )
            {
                relatedObject = it2.next();
                id2 = new Identity(relatedObject, pb);
                if (id.equals(id2))
                {
                    field.set(owner, relatedObject);
+                  childFound = true;
                    break;
                }
            }

+            if ( ! childFound)
+                throw new Exception ("!!! Unresolved reference: " + id + " from " + 
owner);




------------------------------------
Re: Cache and prefetched relationships
From: Oleg Nitz
Date: Mon, 06 Oct 2003 00:16:10 -0700

Hi Carlos,

On Sunday 05 October 2003 14:37, carlos wrote:
> broker.getCollectionByQuery(): Optimised prefetched relationships are only
> useful if object caching is enabled.
>
> Also, using the default cache, it appears that any related objects obtained
> by an optimised SQL IN() clause may be 'garbage collected' before being
> assigned to the 'owning object', causing another database lookup at
> assigment.  I believe I've observed this behaviour retrieving many objects
> (2000+) - Is this correct?
Looking at the ReferencePrefetcher implememntation, I see that this is
possible for references (not for collections). Also I see that this problem
can be easily fixed. I'll do this.

Thanks,
 Oleg


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to