&& (!((UnitOfWorkImpl)parent).isCloneNewObject(originalNewObject)) && (!unitOfWork.isUnregisteredNewObjectInParent(originalNewObject))) {
requiresToRegisterInParent = true;
}
}
ClassDescriptor descriptor = unitOfWork.getDescriptor(clone.getClass());
ObjectBuilder objectBuilder = descriptor.getObjectBuilder();
// This always finds an original different from the clone, even if it has to create one.
// This must be done after special cases have been computed because it registers unregistered new objects.
Object original = unitOfWork.getOriginalVersionOfObjectOrNull(clone, objectChangeSet, descriptor);
// Always merge into the original.
try {
if (original == null) {
// If original does not exist then we must merge the entire object.
original = unitOfWork.buildOriginal(clone);
if (objectChangeSet == null) {
objectBuilder.mergeIntoObject(original, true, clone, this, false, !descriptor.getCopyPolicy().buildsNewInstance());
} else if (!objectChangeSet.isNew()) {
// Once the original is created we must put it in the cache and
// lock it to prevent a reading thread from creating it as well
// there will be no deadlock situation because no other threads
// will be able to reference this object.
original = parent.getIdentityMapAccessorInstance().getWriteLockManager().appendLock(objectChangeSet.getPrimaryKeys(), original, descriptor, this, parent);
objectBuilder.mergeIntoObject(original, true, clone, this, false, !descriptor.getCopyPolicy().buildsNewInstance());
} else {
objectBuilder.mergeChangesIntoObject(original, objectChangeSet, clone, this, !descriptor.getCopyPolicy().buildsNewInstance());
// PERF: If PersistenceEntity is caching the primary key this must be cleared as the primary key may have changed in new objects.
objectBuilder.clearPrimaryKey(original);
}
updateCacheKeyProperties(unitOfWork, original, clone, objectChangeSet, descriptor);
} else if (objectChangeSet == null) {
// PERF: If we have no change set if it is existing, then no merging is required.
// If it is new, then merge the object (normally a new object would have a change set, so this is an odd case.
if (unitOfWork.isCloneNewObject(clone)) {
objectBuilder.mergeIntoObject(original, true, clone, this, false, !descriptor.getCopyPolicy().buildsNewInstance());
updateCacheKeyProperties(unitOfWork, original, clone, objectChangeSet, descriptor);
}
} else {
// Invalidate any object that was marked invalid during the change calculation, even if it was new as multiple flushes
// and custom SQL could still produce invalid new objects.
if (objectChangeSet.shouldInvalidateObject(original, parent)) {
parent.getIdentityMapAccessor().invalidateObject(original);
// no need to update cacheKey properties here
}
if (objectChangeSet.isNew()) {
// PERF: If PersistenceEntity is caching the primary key this must be cleared as the primary key may have changed in new objects.
objectBuilder.clearPrimaryKey(original);
}
// Regardless if the object is new, old, valid or invalid, merging will ensure there is a stub of an object in the
// shared cache for filling in foreign reference relationships. If merge did not occur in some cases (new objects, garbage
// collection objects, object read in a transaction) then no object would be in the shared cache and foreign reference
// mappings would be set to null when they should be set to an object.
if (objectChangeSet.hasChanges()){
//if there are no changes then we just need a reference to the object so skip the merge
// saves trying to lock related objects after the fact producing deadlocks
objectBuilder.mergeChangesIntoObject(original, objectChangeSet, clone, this, false);
updateCacheKeyProperties(unitOfWork, original, clone, objectChangeSet, descriptor);
}
}
} catch (QueryException exception) {
// Ignore validation errors if unit of work validation is suppressed.
// Also there is a very specific case under EJB wrappering where
// a related object may have never been accessed in the unit of work context
// but is still valid, so this error must be ignored.
if (unitOfWork.shouldPerformNoValidation() || (descriptor.hasWrapperPolicy())) {
if ((exception.getErrorCode() != QueryException.BACKUP_CLONE_DELETED) && (exception.getErrorCode() != QueryException.BACKUP_CLONE_IS_ORIGINAL_FROM_PARENT) && (exception.getErrorCode() != QueryException.BACKUP_CLONE_IS_ORIGINAL_FROM_SELF)) {
throw exception;
}
return clone;
} else {