I hate to be a curmudgeon, but it sounds like this might go in the wrong direction, if I understand correctly. You need two sets of functionality: one that the user sees and transparently updates both sides of the relationship; the other, internal, that is called by the external methods and individually updates only one side. Many users would see void add(Room theRoom) and expect to call it instead of void removeObjectFromBothSidesOfRelationshipWithKey(Room theRoom, Site theSite). Or perhaps it's really static void RelationshipHelper.removeObjectFromBothSidesOfRelationshipWithKey (Object oneSide, Object theOtherSide) which can be called from any context and has to be omniscient.

If the removeObjectFromBothSidesOfRelationshipWithKey is intended to be the user-visible method, then it's very descriptive. Is this the user-visible method?

By the way, this is one case where I really miss the "friend" annotation of C++. You don't want the internal methods to be visible to users, just to the classes on the other side of the relationship. Nothing like this semantic exists for Java. :-(

Craig

On Jun 20, 2006, at 6:04 AM, Gentry, Michael (Contractor) wrote:

Monstrous? That was my favorite method name! It stated precisely what
it was doing, too.  :-)  We hardly ever removed anything, so never got
to use removeObjectFromBothSidesOfRelationshipWithKey all that much.
Sigh.

/dev/mrg

PS. For me, it was actually addObject:toBothSidesOfRelationshipWithKey:
... Much better.



-----Original Message-----
From: Andrus Adamchik [mailto:[EMAIL PROTECTED]
Sent: Tuesday, June 20, 2006 2:19 AM
To: [email protected]
Subject: Re: modifying relationship list



"Someone" should write a paper.

Yep :-)

I recall back in my WebObjects/EOF days, instead of using property
setters I always used a generic method with monstrous name of the
Objective C heritage - "addObjectToBothSidesOfRelationshipWithKey"
and its counterpart "removeObjectFromBothSidesOfRelationshipWithKey"
exactly because it helped with graph consistency.

So bidirectional relationship management was one of the first
features in the early Cayenne to address that.

Andrus


On Jun 19, 2006, at 8:51 PM, Craig L Russell wrote:

Hi,

This relationship change issue is a very old one in object modeling
and made even more interesting when mapping to a relational
database, where typically there is only one database column value
that represents both sides of the relationship.

Among the standards for persistence (J2EE CMP, JDO 1, JDO 2, and
EJB3) the requirements are all over the map, with little to guide you.

CMP defines the behavior as I understand Cayenne currently
implements it. That is, the relationship on the other side is
silently changed to be consistent.

JDO 1 is silent on the issue.

JDO 2 defines the behavior as "undefined until commit or flush", at
which point the relationships on both sides are silently changed to
be consistent.

EJB3 is silent, and allows relationships to be inconsistent after
commit.

I believe it is tricky to code defensively if you want to manage
relationships in memory. The issue is the possibility of updating
the relationship from either side. The apparently straightforward
technique is to implement the Room.setSite method to call
oldRoom.remove(this) and newRoom.add(this). And the Site.remove
method to call theRoom.setSite(null) and Site.add method to call
theRoom.setSite(this). But this causes recursion, unless you use
special add, remove, and set methods, that need to be protected
from public callers. That is, define package protected methods
uncoordinatedAdd, uncoordinatedRemove, and uncoordinatedSet that
don't manage the other side, but are called from within the public-
visible implementations of add, remove, and set. But clearly this
is a lot of work for developers, so it's nice that the persistence
implementation does some of the hard work for you.

"Someone" should write a paper.

Craig

On Jun 19, 2006, at 1:12 AM, Tomi NA wrote:

On 6/19/06, Marcin Skladaniec <[EMAIL PROTECTED]> wrote:
Hello
Just run into interesting cayenne feature.

This code:

rooms = site.getRooms();
rooms.remove(aRoom);

would alter the relationship

so aRoom.getSite() is now null

I'm wondering if this is a desired effect ?
This behavior might cause bugs. When someone actually puts code to
know the fact of relationship being changed (ie. put code into Room
setSite() and Site add/removeFromRooms()/setRooms() methods ) he
might be disappointed, as those methods would not run, but the
relationship will change...

I'm wrestling with this issue myself: I've extended the basic
templates so that events are fired on setter calls, but this practice
has the exact shortcomings you pointed out.
Is there a very good reason why cayenne objects don't fire events
on a
lower level (circumventing this problem) out of the box?
Alternatively, if I expand my object code generation templates
further
so that objectA.removeFrom(objectB) fires a property change event for
it's objectA.getBArray() as well as objectB.getToA() - will this
completely solve the problem?

t.n.a.

Craig Russell
Architect, Sun Java Enterprise System http://java.sun.com/products/ jdo
408 276-5638 mailto:[EMAIL PROTECTED]
P.S. A good JDO? O, Gasp!



Craig Russell
Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
408 276-5638 mailto:[EMAIL PROTECTED]
P.S. A good JDO? O, Gasp!

Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to