On Oct 19, 2007, at 10:58 PM, Kevin Menard wrote:
So, looking at the problem again, I see a few issues with
localObject():
1) Overly verbose syntax. Consider:
a.setSomething(b);
versus
a.setSomething((BType) a.getObjectContext().localObject
(b.getObjectId(),
b));
I think this can largely be addressed by adding a new case to
willConnect(), though. If the contexts are different, look at the
persistence state and call localObject() automatically if it makes
sense to.
This helps ease up on the transparency issues as well. Rather than
using
one method for new, unregistered objects (setXXX()) and another for
committed, registered objects (localObject()), you can consolidate
to just
the setter.
I think actually the suggested terse syntax is more confusing on a
number of levels:
* normally a user would assume that after "a.setSomething(b)",
"b.getSomethingElse() == a" (i.e. the reverse relationship is set),
which would not be the case as reverse is set for the clone of "b".
* and on a higher level it would obscure the fact that cross-context
relationships are not possible by design.
I.e. I think explicit is good in this case. Also with JDK 1.5 switch
we can remove the need for casts in many situations, making current
approach less verbose.
2) Loss of transient values.
This could probably be addressed reflectively.
True. Also JPA introduces explicit "transient" attributes - something
we can use to address this issue.
3) Growth of object store.
This is trickier. Ideally, if I call setSomething(a) with 50
different
instances of a, the object store would only have the latest a,
since that's
the only one that's going to be committed. What you have instead
is 50
different instances. With caching, I don't think DB access is the
issue,
but you will have an unbounded memory issue.
I wouldn't worry about that in 3.0 - ObjectStore is using weak
references now, so if you don't have a hard reference in the user
code, the object will be gc'd as needed.
By hiding this in a setter, it may be possible to unregister
the old
object first, thereby limiting the growth.
Not a good idea. Consider this:
1: BType blocal = (BType) a.getObjectContext().localObject
(b.getObjectId(), b);
2: a.setSomething(blocal );
3: a.setSomething( (BType) a.getObjectContext().localObject
(b1.getObjectId(), b1));
4. blocal.doSomething();
"blocal" will be kicked out of the a's context in line 3, but the
user already referenced this object in line 1, so when he later
accesses it on line 4, it is no longer persistent. As I mentioned
above there's no problem anymore with unused object accumulation, and
generally trying to second-guess Cayenne on object graph management
may cause undesired side effects.
Andrus