Re: modifying relationship list

From: Craig L Russell (Craig.Russel..un.COM)
Date: Mon Jun 19 2006 - 12:51:18 EDT

  • Next message: Andrus Adamchik: "Re: modifying relationship list"

    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 <marci..sh.com.au> 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:Craig.Russel..un.com
    P.S. A good JDO? O, Gasp!





    This archive was generated by hypermail 2.0.0 : Mon Jun 19 2006 - 12:52:15 EDT