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);
}
}
}
}
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);
}
}
}
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);
}
}
}
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));
}
}
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);
}
Aggregations