Kevin,
Could a nested context help with your situation?
/dev/mrg
On 10/16/07, Kevin Menard <kmenar..ervprise.com> wrote:
> The problem with localObject is that it does not traverse the whole graph,
> making it practically useless in all but the most trivial situations.
> Manually copying over the graph is doable, but a lot of work for something
> that really should be far easier.
>
> For example, we have customers and orders. All orders are associated with
> customers. We keep the customer info and order info in two different
> contexts for the most part, because we don't want to prematurely commit an
> order while a customer may feel it necessary to change his shipping address,
> for example.
>
> What we've resorted to doing is committing the customer data, then doing a
> requery based on the ObjectID using the order context. This allows us to
> get a fully populated object. Of course, this means more trips to the DB
> and a lot of committing/refetching code. It works, but it hardly makes
> Cayenne transparent.
>
> The whole thing becomes fragile, and there's a lot that Cayenne could do to
> help out. I suppose the problem is exacerbated by the null context problem.
> If we fix that, we'd likely be in much better shape. As it stands, with our
> Tapestry app, we have to stage the objects at page render time to allow the
> association of different objects. That creates for a lot of headaches as
> well, and a lot of context management that really isn't necessary.
>
> --
> Kevin
>
>
> On 10/16/07 9:02 AM, "Andrus Adamchik" <andru..bjectstyle.org> wrote:
>
> > Hi Kevin,
> >
> > Relating (as in "creating a direct reference in a Java sense") two
> > objects belonging to two distinct contexts breaks fundamental Cayenne
> > design, most notably assumptions about uniquing and transaction
> > boundaries. I am -1 on that until somebody persuades me that this is
> > a good idea and explains how to avoid messing up existing
> > assumptions. (FWIW there is a workaround - referencing a peer of a
> > given object in another context via 'localObject').
> >
> >
> > On the other hand the inability to relate two TRANSIENT objects (i.e.
> > objects without a context) is indeed a shortcuming. Here is one way
> > how it might work (following the JPA patterns) :
> >
> > When such relationship is established, we would not attempt to create
> > a reverse relationship (something that would require an
> > EntityResolver to be present). We just create it one-way. So a user
> > can build an object graph of an arbitrary size without a context and
> > then at some point do one of the following with it:
> >
> > * "ObjectContext.registerNewObject(..)" (existing; equivalent to JPA
> > "persist" method)
> > * "ObjectContext.aNewMethod(..)" (does not exist yet; equivalent to
> > JPA "merge" method and somewhat of an equivalent of a "localObject"
> > method).
> >
> > Both would traverse a graph of transient objects (since they are not
> > persistent yet, the graph is assumed to be finite and will not
> > trigger sucking the entire DB in memory), attach them to the context
> > and connect missing reverse relationships. The difference is that in
> > the first case we'd assume that the objects are not yet persistent,
> > while in a second case we'd attempt to match them against existing DB
> > rows. (a typical use of a second case would be receiving XML-
> > serialized stream of objects corresponding to the existing data).
> >
> >
> > But you have something different in mind? Could you elaborate on the
> > use cases?
> >
> > Thanks
> > Andrus
> >
> >
> > On Oct 16, 2007, at 1:25 AM, Kevin Menard wrote:
> >> So, if there is one thing that drives me nuts about Cayenne, it's
> >> managing
> >> ObjectContexts. In particular, you cannot relate two Persistent
> >> objects
> >> without first putting them into an ObjectContext. If one is
> >> committed and
> >> the other is not, you can have them in different contexts, but for
> >> newly
> >> created objects, this is a major pain in the neck.
> >>
> >> Since I've been complaining about it for probably close to three
> >> years now,
> >> I'd like to finally do something about it.
> >>
> >> Here are my rough notes from the airport:
> >>
> >> OK Cases:
> >>
> >> - Objects in same context
> >> - Objects in different contexts, but objects are committed already
> >>
> >> Don't work, but should:
> >>
> >> - Objects in null contexts
> >> - Objects in different contexts, but same data maps and domains
> >>
> >> Very hard to say, probably okay if don't work:
> >>
> >> - Objects in different contexts, contexts have different data maps
> >> - Objects in different contexts, contexts have different data domains
> >>
> >>
> >> As I started actually digging into the code, I ran into a lot of
> >> NPE issues
> >> trying to associate two Persistent objects with no context with one
> >> another.
> >> In an attempt to prevent adding special null-logic handling, I
> >> thought about
> >> applying the Null Object pattern to the problem. The basic idea is
> >> rather
> >> than use null as the default objectContext for CDO, use an instance of
> >> DelayedContext. The problem here is having objects in different
> >> contexts.
> >> So, it appears by fixing one, you can essentially fix the other.
> >>
> >> To address the latter, I was looking to have a Set of
> >> ObjectContexts stored
> >> in either BaseContext or DataContext. When willConnect() is
> >> called, you'd
> >> have something like the following:
> >>
> >> else if (this.getObjectContext().getEntityResolver() ==
> >> object.getObjectContext().getEntityResolver()) {
> >> ((DataContext)
> >> this.getObjectContext()).addContextToMergeWith
> >> (object.getObjectContext());
> >> ((DataContext)
> >> object.getObjectContext()).addContextToMergeWith
> >> (this.getObjectContext());
> >> }
> >> else {
> >> throw new CayenneRuntimeException(
> >> "Cannot set object as destination of
> >> relationship "
> >> + relationshipName
> >> + " because it is in a different
> >> DataMap or
> >> DataDomain.");
> >> }
> >>
> >> (Casts are just an artifact of me screwing around).
> >>
> >> What I'm thinking would happen is that when commitChanges() is
> >> called, the
> >> set of contexts to be merged with will be iterated and any changes
> >> applied
> >> to the current object store / object store graph diff. The
> >> relationship is
> >> bidirectional so that the user can initiate the commit from any object
> >> registered with any context.
> >>
> >> Here is about where I lose it. I'm not as well-versed in the internal
> >> going-ons of Cayenne as I would like to be. It appears Cayenne
> >> goes to
> >> great efforts to essentially cache the graph manipulations so as to
> >> avoid a
> >> full traversal. I really don't know, though.
> >>
> >> Caching ordering of operations could make this tricky, but in
> >> principal
> >> should be wholly doable.
> >>
> >> If anyone has any thoughts on this or can fill in any missing
> >> pieces, I'd
> >> appreciate it. This is really something I'd like to see fixed
> >> sooner rather
> >> than later. I think it may be a requisite for JPA compliance as well.
> >>
> >> --
> >> Kevin
> >>
> >>
> >
>
> --
>
>
>
This archive was generated by hypermail 2.0.0 : Tue Oct 16 2007 - 09:19:27 EDT