Search in sources :

Example 1 with WriteObjectQuery

use of org.eclipse.persistence.queries.WriteObjectQuery in project eclipselink by eclipse-ee4j.

the class CommitManager method commitChangedObjectsForClassWithChangeSet.

/**
 * Commit changed of the objects of the class type in the change set.
 * This allows for the order of the classes to be processed optimally.
 */
protected void commitChangedObjectsForClassWithChangeSet(UnitOfWorkChangeSet uowChangeSet, Class<?> theClass) {
    Map<ObjectChangeSet, ObjectChangeSet> objectChangesList = uowChangeSet.getObjectChanges().get(theClass);
    if (objectChangesList != null) {
        // may be no changes for that class type.
        ClassDescriptor descriptor = null;
        AbstractSession session = getSession();
        Collection<ObjectChangeSet> changes = objectChangesList.values();
        CommitOrderType order = ((UnitOfWorkImpl) session).getCommitOrder();
        if (order != CommitOrderType.NONE) {
            changes = new ArrayList(objectChangesList.values());
            if (order == CommitOrderType.CHANGES) {
                Collections.sort((List) changes, new ObjectChangeSet.ObjectChangeSetComparator());
            } else {
                Collections.sort((List) changes);
            }
        }
        for (ObjectChangeSet changeSetToWrite : changes) {
            Object objectToWrite = changeSetToWrite.getUnitOfWorkClone();
            if (descriptor == null) {
                descriptor = session.getDescriptor(objectToWrite);
            }
            if (!isProcessedCommit(objectToWrite)) {
                // Commit and resume on failure can cause a new change set to be in existing, so need to check here.
                WriteObjectQuery commitQuery = null;
                if (changeSetToWrite.isNew()) {
                    commitQuery = new InsertObjectQuery();
                } else {
                    commitQuery = new UpdateObjectQuery();
                }
                commitQuery.setIsExecutionClone(true);
                commitQuery.setDescriptor(descriptor);
                commitQuery.setObjectChangeSet(changeSetToWrite);
                commitQuery.setObject(objectToWrite);
                commitQuery.cascadeOnlyDependentParts();
                // removed checking session type to set cascade level
                // will always be a unitOfWork so we need to cascade dependent parts
                session.executeQuery(commitQuery);
            }
        }
    }
}
Also used : ClassDescriptor(org.eclipse.persistence.descriptors.ClassDescriptor) CommitOrderType(org.eclipse.persistence.sessions.UnitOfWork.CommitOrderType) ArrayList(java.util.ArrayList) UpdateObjectQuery(org.eclipse.persistence.queries.UpdateObjectQuery) WriteObjectQuery(org.eclipse.persistence.queries.WriteObjectQuery) InsertObjectQuery(org.eclipse.persistence.queries.InsertObjectQuery)

Example 2 with WriteObjectQuery

use of org.eclipse.persistence.queries.WriteObjectQuery in project eclipselink by eclipse-ee4j.

the class ObjectReferenceMapping method update.

/**
 * INTERNAL:
 * Update the private owned part.
 */
protected void update(WriteObjectQuery query) throws DatabaseException, OptimisticLockException {
    if (!shouldObjectModifyCascadeToParts(query)) {
        return;
    }
    Object sourceObject = query.getObject();
    Object attributeValue = getAttributeValueFromObject(sourceObject);
    // If objects are not instantiated that means they are not changed.
    if (!this.indirectionPolicy.objectIsInstantiated(attributeValue)) {
        return;
    }
    // Get the privately owned parts in the memory
    AbstractSession session = query.getSession();
    Object object = getRealAttributeValueFromAttribute(attributeValue, sourceObject, session);
    if (object != null) {
        ObjectChangeSet changeSet = query.getObjectChangeSet();
        if (changeSet != null) {
            ObjectReferenceChangeRecord changeRecord = (ObjectReferenceChangeRecord) query.getObjectChangeSet().getChangesForAttributeNamed(getAttributeName());
            if (changeRecord != null) {
                changeSet = (ObjectChangeSet) changeRecord.getNewValue();
                // PERF: If it is not new, then cascading is not required.
                if (!changeSet.isNew()) {
                    return;
                }
            } else {
                // no changeRecord no change to reference.
                return;
            }
        } else {
            UnitOfWorkChangeSet uowChangeSet = null;
            // Get changeSet for referenced object.
            if (session.isUnitOfWork() && (((UnitOfWorkImpl) session).getUnitOfWorkChangeSet() != null)) {
                uowChangeSet = (UnitOfWorkChangeSet) ((UnitOfWorkImpl) session).getUnitOfWorkChangeSet();
                changeSet = (ObjectChangeSet) uowChangeSet.getObjectChangeSetForClone(object);
                // PERF: If the changeSet is null it must be existing, if it is not new, then cascading is not required.
                if (changeSet == null || !changeSet.isNew()) {
                    return;
                }
            }
        }
        // PERF: Only write dependent object if they are new.
        if ((!query.shouldCascadeOnlyDependentParts()) || (changeSet == null) || changeSet.isNew()) {
            // PERF: Avoid query execution if already written.
            if (session.getCommitManager().isCommitCompletedInPostOrIgnore(object)) {
                return;
            }
            WriteObjectQuery writeQuery = new WriteObjectQuery();
            writeQuery.setIsExecutionClone(true);
            writeQuery.setObject(object);
            writeQuery.setObjectChangeSet(changeSet);
            writeQuery.setCascadePolicy(query.getCascadePolicy());
            session.executeQuery(writeQuery);
        }
    }
}
Also used : ObjectReferenceChangeRecord(org.eclipse.persistence.internal.sessions.ObjectReferenceChangeRecord) WriteObjectQuery(org.eclipse.persistence.queries.WriteObjectQuery) UnitOfWorkChangeSet(org.eclipse.persistence.internal.sessions.UnitOfWorkChangeSet) ObjectChangeSet(org.eclipse.persistence.internal.sessions.ObjectChangeSet) UnitOfWorkImpl(org.eclipse.persistence.internal.sessions.UnitOfWorkImpl) AbstractSession(org.eclipse.persistence.internal.sessions.AbstractSession)

Example 3 with WriteObjectQuery

use of org.eclipse.persistence.queries.WriteObjectQuery in project eclipselink by eclipse-ee4j.

the class DatabaseQueryMechanism method updateObjectAndRowWithReturnRow.

protected void updateObjectAndRowWithReturnRow(Collection returnFields, boolean isFirstCallForInsert) {
    WriteObjectQuery writeQuery = getWriteObjectQuery();
    AbstractRecord outputRow = (AbstractRecord) writeQuery.getProperties().get("output");
    if ((outputRow == null) || outputRow.isEmpty()) {
        return;
    }
    AbstractRecord row = new DatabaseRecord();
    for (Iterator iterator = returnFields.iterator(); iterator.hasNext(); ) {
        DatabaseField field = (DatabaseField) iterator.next();
        if (outputRow.containsKey(field)) {
            row.put(field, outputRow.get(field));
        }
    }
    if (row.isEmpty()) {
        return;
    }
    Object object = writeQuery.getObject();
    ObjectChangeSet objectChangeSet = null;
    if (getSession().isUnitOfWork()) {
        objectChangeSet = writeQuery.getObjectChangeSet();
        if ((objectChangeSet == null) && (((UnitOfWorkImpl) getSession()).getUnitOfWorkChangeSet() != null)) {
            objectChangeSet = (ObjectChangeSet) ((UnitOfWorkImpl) getSession()).getUnitOfWorkChangeSet().getObjectChangeSetForClone(object);
        }
    }
    getDescriptor().getObjectBuilder().assignReturnRow(object, writeQuery.getSession(), row, objectChangeSet);
    Object primaryKey = null;
    if (isFirstCallForInsert) {
        AbstractRecord pkToModify = new DatabaseRecord();
        List<DatabaseField> primaryKeyFields = getDescriptor().getPrimaryKeyFields();
        for (int i = 0; i < primaryKeyFields.size(); i++) {
            DatabaseField field = primaryKeyFields.get(i);
            if (row.containsKey(field)) {
                pkToModify.put(field, row.get(field));
            }
        }
        if (!pkToModify.isEmpty()) {
            primaryKey = getDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(object, getSession());
            writeQuery.setPrimaryKey(primaryKey);
            // Now I need to update the row
            getModifyRow().putAll(pkToModify);
            getDescriptor().getObjectBuilder().addPrimaryKeyForNonDefaultTable(getModifyRow(), object, getSession());
        }
    }
    if (objectChangeSet != null) {
        if (primaryKey != null) {
            objectChangeSet.setId(primaryKey);
        }
    }
}
Also used : WriteObjectQuery(org.eclipse.persistence.queries.WriteObjectQuery) DatabaseRecord(org.eclipse.persistence.sessions.DatabaseRecord) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField) AbstractRecord(org.eclipse.persistence.internal.sessions.AbstractRecord) Iterator(java.util.Iterator) ObjectChangeSet(org.eclipse.persistence.internal.sessions.ObjectChangeSet)

Example 4 with WriteObjectQuery

use of org.eclipse.persistence.queries.WriteObjectQuery in project eclipselink by eclipse-ee4j.

the class DatabaseQueryMechanism method updateObjectForWriteWithChangeSet.

/**
 * Update the object.
 * This is used by the unit-of-work update.
 */
public void updateObjectForWriteWithChangeSet() {
    WriteObjectQuery writeQuery = getWriteObjectQuery();
    ObjectChangeSet changeSet = writeQuery.getObjectChangeSet();
    Object object = writeQuery.getObject();
    ClassDescriptor descriptor = getDescriptor();
    DescriptorQueryManager queryManager = descriptor.getQueryManager();
    AbstractSession session = getSession();
    CommitManager commitManager = session.getCommitManager();
    // check for user-defined query
    if (// this is not a user-defined query
    (!writeQuery.isUserDefined()) && // there is a user-defined query
    queryManager.hasUpdateQuery() && isExpressionQueryMechanism()) {
        // this is not a hand-coded call (custom SQL etc.)
        // This must be done here because the user defined update does not use a changeset so it will not be set otherwise
        commitManager.markPreModifyCommitInProgress(object);
        performUserDefinedUpdate();
        return;
    }
    // This must be done after the custom query check, otherwise it will be done twice.
    commitManager.markPreModifyCommitInProgress(object);
    DescriptorEventManager eventManager = descriptor.getEventManager();
    if (changeSet.hasChanges()) {
        // PERF: Avoid events if no listeners.
        if (eventManager.hasAnyEventListeners()) {
            DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.PreUpdateWithChangesEvent, writeQuery);
            eventManager.executeEvent(event);
            // PreUpdateWithChangesEvent listeners may have altered the object - should recalculate the change set.
            UnitOfWorkChangeSet uowChangeSet = (UnitOfWorkChangeSet) ((UnitOfWorkImpl) session).getUnitOfWorkChangeSet();
            if (!uowChangeSet.isChangeSetFromOutsideUOW() && writeQuery.getObjectChangeSet().shouldRecalculateAfterUpdateEvent()) {
                // It is first cleared then re-populated by calculateChanges method.
                if (!descriptor.getObjectChangePolicy().isAttributeChangeTrackingPolicy()) {
                    // clear the change set without clearing the maps keys since they are not alterable by the event
                    // if the map is changed, it will be changed in the owning object and the
                    // change set will be changed there as well.
                    writeQuery.getObjectChangeSet().clear(false);
                }
                if (descriptor.getObjectChangePolicy().calculateChangesForExistingObject(object, uowChangeSet, ((UnitOfWorkImpl) session), descriptor, false) == null) {
                    // calculateChanges returns null in case the changeSet doesn't have changes.
                    // It should be removed from the list of ObjectChangeSets that have changes in uowChangeSet.
                    uowChangeSet.getAllChangeSets().remove(writeQuery.getObjectChangeSet());
                }
            }
        }
    }
    // Verify if deep shallow modify is turned on
    if (writeQuery.shouldCascadeParts()) {
        queryManager.preUpdate(writeQuery);
    }
    // The row must not be built until after preUpdate in case the object reference has changed.
    // For a user defined update in the uow to row must be built twice to check if any update is required.
    writeQuery.setModifyRow(descriptor.getObjectBuilder().buildRowForUpdateWithChangeSet(writeQuery));
    Boolean shouldModifyVersionField = changeSet.shouldModifyVersionField();
    if (!getModifyRow().isEmpty() || shouldModifyVersionField != null || changeSet.hasCmpPolicyForcedUpdate()) {
        // If user defined the entire row is required. Must not be built until change is known.
        if (writeQuery.isUserDefined() || writeQuery.isCallQuery()) {
            writeQuery.setModifyRow(descriptor.getObjectBuilder().buildRow(object, session, WriteType.UNDEFINED));
        }
        OptimisticLockingPolicy lockingPolicy = descriptor.getOptimisticLockingPolicy();
        // Update the write lock field if required.
        if (lockingPolicy != null) {
            lockingPolicy.addLockValuesToTranslationRow(writeQuery);
            // Do not lock an object that has previously been optimistically locked within the RWUoW
            boolean existingOptimisticLock = false;
            if (session instanceof RepeatableWriteUnitOfWork) {
                RepeatableWriteUnitOfWork uow = (RepeatableWriteUnitOfWork) session;
                if (uow.getOptimisticReadLockObjects().get(object) != null && uow.getCumulativeUOWChangeSet() != null && uow.getCumulativeUOWChangeSet().getObjectChangeSetForClone(object) != null) {
                    existingOptimisticLock = true;
                }
            }
            if (!existingOptimisticLock) {
                // or if there is no forced update and modifyRow has modifications
                if ((shouldModifyVersionField != null && shouldModifyVersionField) || !getModifyRow().isEmpty()) {
                    // Update the row with newer lock value.
                    lockingPolicy.updateRowAndObjectForUpdate(writeQuery, object);
                } else if (!shouldModifyVersionField && (lockingPolicy instanceof VersionLockingPolicy)) {
                    // Add the existing write lock value to the for a "read" lock (requires something to update).
                    ((VersionLockingPolicy) lockingPolicy).writeLockValueIntoRow(writeQuery, object);
                }
            }
        }
        if (descriptor.hasSerializedObjectPolicy()) {
            descriptor.getSerializedObjectPolicy().putObjectIntoRow(getModifyRow(), object, session);
        }
        // PERF: Avoid events if no listeners.
        if (eventManager.hasAnyEventListeners()) {
            DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.AboutToUpdateEvent, writeQuery);
            event.setRecord(getModifyRow());
            eventManager.executeEvent(event);
        }
        if (QueryMonitor.shouldMonitor()) {
            QueryMonitor.incrementUpdate(getWriteObjectQuery());
        }
        int rowCount = updateObject();
        if (rowCount < 1) {
            if (session.hasEventManager()) {
                session.getEventManager().noRowsModified(writeQuery, object);
            }
        }
        if (lockingPolicy != null) {
            lockingPolicy.validateUpdate(rowCount, object, writeQuery);
        }
    }
    commitManager.markPostModifyCommitInProgress(object);
    // Verify if deep shallow modify is turned on
    if (writeQuery.shouldCascadeParts()) {
        queryManager.postUpdate(writeQuery);
    }
    if ((descriptor.getHistoryPolicy() != null) && descriptor.getHistoryPolicy().shouldHandleWrites()) {
        descriptor.getHistoryPolicy().postUpdate(writeQuery);
    }
    // PERF: Avoid events if no listeners.
    if (eventManager.hasAnyEventListeners()) {
        eventManager.executeEvent(new DescriptorEvent(DescriptorEventManager.PostUpdateEvent, writeQuery));
    }
}
Also used : DescriptorQueryManager(org.eclipse.persistence.descriptors.DescriptorQueryManager) ClassDescriptor(org.eclipse.persistence.descriptors.ClassDescriptor) CommitManager(org.eclipse.persistence.internal.sessions.CommitManager) UnitOfWorkChangeSet(org.eclipse.persistence.internal.sessions.UnitOfWorkChangeSet) VersionLockingPolicy(org.eclipse.persistence.descriptors.VersionLockingPolicy) ObjectChangeSet(org.eclipse.persistence.internal.sessions.ObjectChangeSet) DescriptorEvent(org.eclipse.persistence.descriptors.DescriptorEvent) WriteObjectQuery(org.eclipse.persistence.queries.WriteObjectQuery) DescriptorEventManager(org.eclipse.persistence.descriptors.DescriptorEventManager) RepeatableWriteUnitOfWork(org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork) AbstractSession(org.eclipse.persistence.internal.sessions.AbstractSession) OptimisticLockingPolicy(org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy)

Example 5 with WriteObjectQuery

use of org.eclipse.persistence.queries.WriteObjectQuery in project eclipselink by eclipse-ee4j.

the class DatabaseQueryMechanism method updateForeignKeyFieldAfterInsert.

/**
 * Update the foreign key fields when resolving a bi-directonal reference in a UOW.
 * This must always be dynamic as it is called within an insert query and is really part of the insert
 * and does not fire update events or worry about locking.
 */
protected void updateForeignKeyFieldAfterInsert() {
    WriteObjectQuery writeQuery = getWriteObjectQuery();
    Object object = writeQuery.getObject();
    writeQuery.setPrimaryKey(getDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(object, getSession()));
    // reset the translation row because the insert has occurred and the id has
    // been assigned to the object, but not the row
    writeQuery.setTranslationRow(getDescriptor().getObjectBuilder().buildRowForTranslation(object, getSession()));
    updateForeignKeyFieldAfterInsert(writeQuery);
}
Also used : WriteObjectQuery(org.eclipse.persistence.queries.WriteObjectQuery)

Aggregations

WriteObjectQuery (org.eclipse.persistence.queries.WriteObjectQuery)22 ObjectChangeSet (org.eclipse.persistence.internal.sessions.ObjectChangeSet)10 AbstractSession (org.eclipse.persistence.internal.sessions.AbstractSession)7 UnitOfWorkChangeSet (org.eclipse.persistence.internal.sessions.UnitOfWorkChangeSet)7 InsertObjectQuery (org.eclipse.persistence.queries.InsertObjectQuery)7 ClassDescriptor (org.eclipse.persistence.descriptors.ClassDescriptor)6 DescriptorEvent (org.eclipse.persistence.descriptors.DescriptorEvent)6 CommitManager (org.eclipse.persistence.internal.sessions.CommitManager)5 ContainerPolicy (org.eclipse.persistence.internal.queries.ContainerPolicy)4 UnitOfWorkImpl (org.eclipse.persistence.internal.sessions.UnitOfWorkImpl)4 DescriptorEventManager (org.eclipse.persistence.descriptors.DescriptorEventManager)3 DescriptorQueryManager (org.eclipse.persistence.descriptors.DescriptorQueryManager)3 AbstractRecord (org.eclipse.persistence.internal.sessions.AbstractRecord)3 VersionLockingPolicy (org.eclipse.persistence.descriptors.VersionLockingPolicy)2 OptimisticLockingPolicy (org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy)2 RepeatableWriteUnitOfWork (org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork)2 DatabaseRecord (org.eclipse.persistence.sessions.DatabaseRecord)2 ArrayList (java.util.ArrayList)1 Iterator (java.util.Iterator)1 DatabaseCall (org.eclipse.persistence.internal.databaseaccess.DatabaseCall)1