Index: src/java/oracle/toplink/essentials/internal/descriptors/ObjectBuilder.java =================================================================== RCS file: /cvs/glassfish/entity-persistence/src/java/oracle/toplink/essentials/internal/descriptors/ObjectBuilder.java,v retrieving revision 1.15 diff -c -r1.15 ObjectBuilder.java *** src/java/oracle/toplink/essentials/internal/descriptors/ObjectBuilder.java 18 Aug 2006 17:59:26 -0000 1.15 --- src/java/oracle/toplink/essentials/internal/descriptors/ObjectBuilder.java 22 Sep 2006 01:15:02 -0000 *************** *** 2069,2074 **** --- 2069,2090 ---- } /** + * INTERNAL: + * Cascade merge of the contents of a registered object, this merge algorthim is dependent on the merge manager. + */ + public void cascadeMergeIntoObject(Object object, boolean isUnInitialized, MergeManager mergeManager) { + // PERF: Avoid synchronized enumerator as is concurrency bottleneck. + Vector mappings = getDescriptor().getMappings(); + for (int index = 0; index < mappings.size(); index++) { + DatabaseMapping mapping = (DatabaseMapping)mappings.get(index); + if(mapping instanceof ForeignReferenceMapping + && ((ForeignReferenceMapping)mapping).shouldMergeCascadeParts(mergeManager)){ + mapping.mergeIntoObject(object, isUnInitialized, object, mergeManager); + } + } + } + + /** * Clones the attributes of the specified object. This is called only from unit of work. * The domainObject sent as parameter is always a copy from the parent of unit of work. */ Index: src/java/oracle/toplink/essentials/internal/sessions/MergeManager.java =================================================================== RCS file: /cvs/glassfish/entity-persistence/src/java/oracle/toplink/essentials/internal/sessions/MergeManager.java,v retrieving revision 1.6 diff -c -r1.6 MergeManager.java *** src/java/oracle/toplink/essentials/internal/sessions/MergeManager.java 20 Apr 2006 20:32:05 -0000 1.6 --- src/java/oracle/toplink/essentials/internal/sessions/MergeManager.java 22 Sep 2006 01:15:03 -0000 *************** *** 387,402 **** ClassDescriptor descriptor = getSession().getDescriptor(rmiClone); Object registeredObject = registerObjectForMergeCloneIntoWorkingCopy(rmiClone); - if (registeredObject == rmiClone) { - //need to find better better fix. prevents merging into itself. - return rmiClone; - } - boolean changeTracked = false; try { ObjectBuilder builder = descriptor.getObjectBuilder(); ! if (descriptor.usesVersionLocking()) { VersionLockingPolicy policy = (VersionLockingPolicy) descriptor.getOptimisticLockingPolicy(); if (policy.isStoredInObject()) { Object currentValue = builder.extractValueFromObjectForField(registeredObject, policy.getWriteLockField(), session); --- 387,397 ---- ClassDescriptor descriptor = getSession().getDescriptor(rmiClone); Object registeredObject = registerObjectForMergeCloneIntoWorkingCopy(rmiClone); boolean changeTracked = false; try { ObjectBuilder builder = descriptor.getObjectBuilder(); ! if (registeredObject != rmiClone && descriptor.usesVersionLocking()) { VersionLockingPolicy policy = (VersionLockingPolicy) descriptor.getOptimisticLockingPolicy(); if (policy.isStoredInObject()) { Object currentValue = builder.extractValueFromObjectForField(registeredObject, policy.getWriteLockField(), session); *************** *** 410,417 **** // Toggle change tracking during the merge. descriptor.getObjectChangePolicy().dissableEventProcessing(registeredObject); ! // Merge into the clone from the original, use clone as backup as anything different should be merged. ! builder.mergeIntoObject(registeredObject, false, rmiClone, this); } finally { descriptor.getObjectChangePolicy().enableEventProcessing(registeredObject); } --- 405,417 ---- // Toggle change tracking during the merge. descriptor.getObjectChangePolicy().dissableEventProcessing(registeredObject); ! if(registeredObject == rmiClone){ ! // GF#1139 Cascade merge operations even if it's already managed ! builder.cascadeMergeIntoObject(registeredObject, false, this); ! } else { ! // Merge into the clone from the original, use clone as backup as anything different should be merged. ! builder.mergeIntoObject(registeredObject, false, rmiClone, this); ! } } finally { descriptor.getObjectChangePolicy().enableEventProcessing(registeredObject); }