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]