cayenne-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Mike Kienenberger <>
Subject Re: Making a copy of an object that is persisted by Cayenne
Date Thu, 19 Jan 2012 14:27:13 GMT
Yes, I might have taken a look at serialization-based approach if I
heard about it sooner, since this particular project is completely
request-scoped, and I use data object serialization already.

But I was able to get the ObjectDetachOperation converted into a
DeepCopyOperation, and it seems to be working exactly as needed.   My
only issue is that my copied relationships seem to disappear when I go
to commit them.   Because this is my heavily-modified cayenne 1.2 code
base supporting outer joins and split expressions, with field-level
auditing, and because I only saved my patches against 1.2 instead of
the entire 1.2 code base, I'm having a hard time debugging it.   I
don't really know exactly what version of 1.2 I was using when I made
the changes, but it appears to have been some snapshot rather than a
release version.

So once I finally get a recompiled version of cayenne with the changes
I need working again, I can try to make more progress on this issue.

Or I might just try upgrading to 3.0 or 3.1 since it now supports
outer joins and split expressions.

On Thu, Jan 19, 2012 at 2:29 AM, Andrus Adamchik <> wrote:
> Hi Mike,
> Sorry for late reply. Indeed I have only a vague recollection of 1.2 APIs.
> A couple of years back I was trying to solve a similar problem in a generic fashion via
controlled serialization/deserialization. See the source code in sandbox:
> Subgraph object is a descriptor of the relationships that you want to operate on. SubgraphSerializer
and SubgraphDeserializer are the actual processors doing the work. IIRC the solution worked,
but required some performance tweaking for large data sets to avoid fetching the entire DB
in memory. Since then my actual use case was solved by a bunch of SQL scripts, so I didn't
have a chance to try it out in production.
> I wonder if with some work this can be used for cloning too... You can already do it
by serializing to XML in memory, and then deserializing, which is not very efficient... But
probably a new SubgraphCloner can be added to SubgraphSerializer / SubgraphDeserializer pair,
using similar algorithms, but bypassing the XML.
> The basic model and algorithms behind cayenne-serialization are sound and user-friendly,
but the actual implementation will require some work, and it would be cool if somebody could
find time to evaluate it and make it 100% usable.
> Cheers,
> Andrus
> On Jan 12, 2012, at 8:28 PM, Mike Kienenberger wrote:
>> So it looks like ObjectDetachOperation does the opposite of what I
>> want -- clones via an including set of path specs (represented by the
>> PrefetchTreeNode).  I think it would be too difficult to build an
>> inclusive PrefetchTreeNode.  These objects are also all transient.
>> DeepMergeOperation seems to be the way to go (specifying excludes by
>> creating a custom Class descriptor), but this method reuses existing
>> object rather than creating new objects.
>> I'm guessing what I need to do is to copy the DeepMergeOperation class
>> and change the "localObject" to a "createAndRegisterNewObject" call.
>> On Thu, Jan 12, 2012 at 11:51 AM, Mike Kienenberger <> wrote:
>>> Andrus,
>>> I find myself in the same situation and environment as Eric Lazarus
>>> who originally posed this question.
>>> Unfortunately, he never answered your questions, so now I have an
>>> unrealistic hope that you can answer them for my situation despite it
>>> being 5 1/2 years ago.  :-)
>>> [Continued below your original response]
>>> On Thu Jun 01 2006 - 11:46:10 EDT, Andrus Adamchik wrote,
>>> =================================================
>>> Cayenne 1.2 has some unadvertised object graph cloning facilities
>>> centered around ClassDescriptor interface (that has a 'shallowMerge'
>>> method). I've written a few specialized operations, such as
>>> DeepMergeOperation and ObjectDetachOperation in Util package that are
>>> doing smart deep copy for some internal use.
>>> Could you explain a bit what is the purpose of the copy operation and
>>> whether the original and cloned objects are (or should be) registered
>>> with a DataContext and whether this is the same DataContext for the
>>> original and the clone.
>>> =================================================
>>> In my situation, also on a Cayenne 1.2 project, I have a document
>>> record with a number of to-many joins, and some of those to-many joins
>>> also have other to-many joins.
>>> I have been asked to provide a function that will copy the original
>>> document (and all related records), changing only the primary keys and
>>> the document_number field.
>>> The original object is a committed object registered with a data context.
>>> The cloned object eventually has to be in a data context, although I
>>> can certainly fetch it manually afterward myself if need be.
>>> It doesn't matter to me if the two objects are in the same data context.
>>> I could certainly go through and create specific deepCopy() methods on
>>> each of the related entities, but I'd rather not have to do so.
>>> It is possible that some of the relationships will need to be excluded
>>> from the deep copy, but I can always pre-break those beforehand and
>>> then set them back.
>>> Ideally, I would want to have a method like
>>> Document copiedDoc = originalDocument.deepCopy(<List of path specs to
>>> exclude in the deep copy>);
>>> Like I said, it's pretty unreasonable to expect you to remember what
>>> you were working on so long ago, so I'm going to try to see how you
>>> used DeepMergeOperation and ObjectDetachOperation in hopes of figuring
>>> it out myself as soon as I post this, but any hints would be
>>> appreciated.
>>> Before I found this message, I was going to do this on my own by
>>> iterating through the relationships and attributes of the entity
>>> recursively, excluding matching paths.

View raw message