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

Reply via email to