Re: Cayenne 101

From: Robert Zeigler (robert.zeigle..mail.com)
Date: Fri Dec 26 2008 - 17:01:58 EST

  • Next message: Pierre Lavignotte: "Re: Cayenne 101"

    Shouldn't have to do that, but it depends, in part, on how things are
    modeled.
    Cayenne can manage the relationship object graph for you.

    In older versions of cayenne, you had to explicitly register E1 before
    associating it with E2. In current versions of cayenne, as long as /
    one/ of the entities is registered with an object context, you can
    associate the two entities, and if the other is not registered, it
    will be auto-registered (note: if both objects are registered, but
    they are registered to different object contexts, you'll get an
    exception).

    So, for Question 1:
            E2 e2 = new E2();
            e1.addToE2List(e2);
            or

            E2 e2 = new E2();
            e2.setE1(e1);

            or
            
            //following is 3.0M5-based code
            ObjectContext oc = BaseContext.getThreadObjectContext();
            E2 e2 = oc.newObject(E2.class);
            e2.setE1(e1);
            
            or
            ObjectContext oc = BaseContext.getThreadObjectContext();
            E2 e2 = oc.newObject(E2.class);
            e1.addToE2List(e2);

    Any of those will work just fine and be equivalent.

    For Question 2:
            At least in 3.0, as long as your relationships are properly mapped,
    simply doing:
            ObjectContext oc = BaseContext.getThreadObjectContext();
            oc.deleteObject(e2);
            oc.commitChanges();

    Will work, and the object should be removed from all associated
    relationships.
            
    For example, using 3.0M5, I just wrote the following test (which
    passes) in a project of mine to illustrate the behavior.
    Note that "createRole" is a convenience method which creates a
    UserRole, registers it with the thread-bound ObjectContext, sets
    default properties, and commits the object to the database.
    UserRole has a one-to-many relationship with Parent. Conversely,
    Parent has a ManyToOne relationship with UserRole.

            public void testRelationshipDeleting() {
                    ObjectContext oc = BaseContext.getThreadObjectContext();
                    UserRole role = createRole("test role");
                    
                    Parent p = new Parent();
                    p.setUsername("somelogin");//username and password are required.
                    p.setPassword("somepassword");
                    p.setUserRole(role);
                    
                    assertTrue(role.getParentsInRole().contains(p)); //note that even
    before the commit, cayenne has updated the object graph so the parent
    is in the list.
                    
                    oc.commitChanges();
                    
                    assertTrue(role.getParentsInRole().contains(p));
                    
                    oc.deleteObject(p);
                    assertFalse(role.getParentsInRole().contains(p));//note that even
    before committing changes, the parent has been removed from the
    relationship.
                    
                    oc.commitChanges();
                    assertFalse(role.getParentsInRole().contains(p));
            }

    One line of code you have below has me raising my eyebrows a bit, and
    that's the dc.commitChangesToParent(). That's only used/needed for
    nested data contexts. Based on the rest of your code, it doesn't look
    like you're using nested data contexts. See: http://cayenne.apache.org/doc/nested-datacontexts.html
      for more information.
    Suffice it to say that you probably don't need
    dc.commitChangesToParent();

    Robert

    On Dec 26, 2008, at 12/261:05 PM , Joe Baldwin wrote:

    > This accounts for the totally weird results. Ref to "what [I]
    > want". As usual with software, I would like to make a change in one
    > place vs two or three places. I guess I am still thinking of this
    > from a RDB point of view. It sounds like you are telling me, that I
    > must update all of the relationships via explicit code references
    > and then commitChanges.
    >
    > Is this correct?
    >
    >
    >
    > On Dec 26, 2008, at 2:19 PM, Pierre Lavignotte wrote:
    >
    >> Hi Joe,
    >>
    >> Question 1 :
    >>
    >> you can't call the object constructor. Use the DataContext method
    >> instead
    >> because it will register the object too.
    >>
    >> Question 2 :
    >> It depends what you want !
    >>
    >> DataContext dc = DataContext.
    >>
    >> getThreadDataContext();
    >>> E1.getE2List().remove(e2);
    >>> dc.commitChanges();
    >>
    >> This will remove the link between E1 and E2 but E2 will still exist.
    >>
    >> DataContext dc = DataContext.
    >>
    >> getThreadDataContext();
    >>> dc.deleteObject(e2);
    >>> dc.commitChangesToParent();
    >>> dc.commitChanges();
    >>
    >>
    >> This will delete E2... but I think it will still be present in
    >> E1.getE2List() because the list can be in memory.
    >> I know it's not logical but I'm quite sure I allready encontered
    >> this case.
    >>
    >> I use Cayenne 2.0.4 so Cayenne 3.0 can differ in some points.
    >>
    >> Pierre
    >>
    >>
    >> Cordialement,
    >> Pierre Lavignotte
    >> Ingénieur Conception & Développement
    >> http://pierre.lavignotte.googlepages.com
    >>
    >>
    >> On Fri, Dec 26, 2008 at 6:32 PM, Joe Baldwin
    >> <jfbaldwi..arthlink.net>wrote:
    >>
    >>> I have a few questions about best practices. I have done some
    >>> experimenting, have read what I could find, and have some
    >>> questions about
    >>> some elementary Cayenne usage concerning Add & Delete with a
    >>> Parent-ChildList design. (I have recently experienced some odd
    >>> behavior
    >>> that may be due to a fundamental misunderstanding of DataContext
    >>> rules.)
    >>>
    >>> Environment: I am using 3.0 M4 with MySQL and Tomcat JSP
    >>> DataContext: I am getting the context using:
    >>> DataContext.getThreadDataContext();
    >>> Example Design:
    >>> E1 has a list of E2's
    >>> that is:
    >>> E2 is a child of E1 and is a many-to-one relationship.
    >>> The E1 relationship is called "E2List" and the reverse
    >>> relationship
    >>> on E2 is called "E1".
    >>>
    >>> Questions:
    >>> 1. When creating and associating E2 children is it more proper to
    >>> do the
    >>> following:
    >>>
    >>> DataContext dc = DataContext.getThreadDataContext();
    >>> ** [get E1 via a DataContext query]
    >>> E2 e2 = new E2();
    >>> e2.setE1(e1); // I **assume** this registers e2 with the
    >>> Context &
    >>> adds e2 to e1's list
    >>> dc.commitChanges();
    >>>
    >>> OR do you need to do as your example suggests:
    >>>
    >>> DataContext dc = DataContext.getThreadDataContext();
    >>> E2 e2 = (E2) dc.newObject(E2.class);
    >>> e2.setE1(e1);
    >>> dc.commitChanges();
    >>>
    >>> OR is there a better way?
    >>>
    >>> 2. Removal of a Child
    >>> Can you remove the child using:
    >>> DataContext dc = DataContext.getThreadDataContext();
    >>> dc.deleteObject(e2);
    >>> dc.commitChangesToParent();
    >>> dc.commitChanges();
    >>>
    >>> or must you do it via the parent:
    >>> DataContext dc = DataContext.getThreadDataContext();
    >>> E1.getE2List().remove(e2);
    >>> dc.commitChanges();
    >>>
    >>> (Note: the second method seems to work better.)
    >>>
    >>> Thanks,
    >>> Joe
    >>>
    >>>
    >



    This archive was generated by hypermail 2.0.0 : Fri Dec 26 2008 - 17:02:39 EST