Cees de Groot reports that
I have a One -> Many mapping and, at the Many side, a
1:1 mapping back.
Both One and Many are part of a filtered type hierarchy.
I have a processing loop (One is an object, Many
represents the state)
that fetches One, fetches the current Many (the one
having 'processed =
0'), processes it, which will likely result in the
creation and addition
of a new Many (representing the next unprocessed
state). The thing then
loops as long as there's work to do (a Many having
'processed = 0').
What happened this morning: I read the One, the Many,
later I walked the
One->Many relation which faulted the proxy which
returned a *new* Many
which had a proxy which then faulted a *new* One, which ...
So everytime I traversed an uninstantiated proxy, I got
a copy of the
object fresh from the DB. Judging the code, a
relationship query does
indeed never hit the cache, which is bad.
I patched this by adding in
RelationShipMapping>>mapFromRow:intoObject:inElementBuilder
the
following code:
hit := descriptor session cacheAt: (mappingCriteria
primaryKeyFromDictionary: parameters) forClass:
referenceClass ifNone:
[nil].
hit ifNotNil: [^self setValueIn: anObject to: hit].
just before 'self setValueIn: anObject to: (self
shouldProxy....)'
The effect is that the 'One' reference in Many is never
set to a proxy
but to the One object in the cache, which is what you
want (because then
after traversing One->Many->One you have an
instantiated Many collection
in One and never have to worry about proxies again).
----------------------------
and Andrei Sobchuck suggests
try to modify AbstractReadQuery>>checkCacheWithParameters:
After line with 'primaryKey isNil ifTrue: [^nil].'
Add such line: 'criteria targetKeys first isPrimaryKey
ifFalse: [^nil].'
--------------
I haven't looked at the code yet, but my first guess is
that there's a problem with caching and non-primary key
relationships (it's possible the filtered inheritance
is also involved somehow).