use of org.eclipse.persistence.internal.sessions.DirectToFieldChangeRecord in project eclipselink by eclipse-ee4j.
the class ObjectBuilder method getBaseChangeRecordForField.
/**
* Return the base ChangeRecord for the given DatabaseField.
* The object and all its relevant aggregates must exist.
* The returned ChangeRecord is
* either DirectToFieldChangeRecord or TransformationMappingChangeRecord,
* or null.
*/
public ChangeRecord getBaseChangeRecordForField(ObjectChangeSet objectChangeSet, Object object, DatabaseField databaseField, AbstractSession session) {
DatabaseMapping mapping = getMappingForField(databaseField);
// Drill down through the mappings until we get the direct mapping to the databaseField.
while (mapping.isAggregateObjectMapping()) {
String attributeName = mapping.getAttributeName();
Object aggregate = mapping.getAttributeValueFromObject(object);
ClassDescriptor referenceDescriptor = mapping.getReferenceDescriptor();
AggregateChangeRecord aggregateChangeRecord = (AggregateChangeRecord) objectChangeSet.getChangesForAttributeNamed(attributeName);
if (aggregateChangeRecord == null) {
aggregateChangeRecord = new AggregateChangeRecord(objectChangeSet);
aggregateChangeRecord.setAttribute(attributeName);
aggregateChangeRecord.setMapping(mapping);
objectChangeSet.addChange(aggregateChangeRecord);
}
ObjectChangeSet aggregateChangeSet = (ObjectChangeSet) aggregateChangeRecord.getChangedObject();
if (aggregateChangeSet == null) {
aggregateChangeSet = referenceDescriptor.getObjectBuilder().createObjectChangeSet(aggregate, (UnitOfWorkChangeSet) objectChangeSet.getUOWChangeSet(), session);
aggregateChangeRecord.setChangedObject(aggregateChangeSet);
}
mapping = referenceDescriptor.getObjectBuilder().getMappingForField(databaseField);
objectChangeSet = aggregateChangeSet;
object = aggregate;
}
String attributeName = mapping.getAttributeName();
if (mapping.isAbstractDirectMapping()) {
DirectToFieldChangeRecord changeRecord = (DirectToFieldChangeRecord) objectChangeSet.getChangesForAttributeNamed(attributeName);
if (changeRecord == null) {
changeRecord = new DirectToFieldChangeRecord(objectChangeSet);
changeRecord.setAttribute(attributeName);
changeRecord.setMapping(mapping);
objectChangeSet.addChange(changeRecord);
}
return changeRecord;
} else if (mapping.isTransformationMapping()) {
TransformationMappingChangeRecord changeRecord = (TransformationMappingChangeRecord) objectChangeSet.getChangesForAttributeNamed(attributeName);
if (changeRecord == null) {
changeRecord = new TransformationMappingChangeRecord(objectChangeSet);
changeRecord.setAttribute(attributeName);
changeRecord.setMapping(mapping);
objectChangeSet.addChange(changeRecord);
}
return changeRecord;
} else {
session.log(SessionLog.FINEST, SessionLog.QUERY, "field_for_unsupported_mapping_returned", databaseField, getDescriptor());
return null;
}
}
use of org.eclipse.persistence.internal.sessions.DirectToFieldChangeRecord in project eclipselink by eclipse-ee4j.
the class ObjectBuilder method assignReturnValueToMapping.
/**
* INTERNAL:
* Assign values from objectRow to the object through the mapping.
* If not null changeSet must correspond to object. changeSet is updated with all of the field values in the row.
*/
protected void assignReturnValueToMapping(Object object, ReadObjectQuery query, AbstractRecord row, DatabaseField field, DatabaseMapping mapping, Collection handledMappings, ObjectChangeSet changeSet) {
if ((handledMappings != null) && handledMappings.contains(mapping)) {
return;
}
if (mapping.isAbstractDirectMapping()) {
if (changeSet != null && (!changeSet.isNew() || (query.getDescriptor() != null && query.getDescriptor().shouldUseFullChangeSetsForNewObjects()))) {
DirectToFieldChangeRecord changeRecord = (DirectToFieldChangeRecord) changeSet.getChangesForAttributeNamed(mapping.getAttributeName());
Object oldAttributeValue = null;
if (changeRecord == null) {
oldAttributeValue = mapping.getAttributeValueFromObject(object);
}
// use null cachekey to ensure we build directly into the attribute
Object attributeValue = mapping.readFromRowIntoObject(row, null, object, null, query, query.getSession(), true);
if (changeRecord == null) {
// Don't use ObjectChangeSet.updateChangeRecordForAttributeWithMappedObject to avoid unnecessary conversion - attributeValue is already converted.
changeRecord = (DirectToFieldChangeRecord) ((AbstractDirectMapping) mapping).internalBuildChangeRecord(attributeValue, oldAttributeValue, changeSet);
changeSet.addChange(changeRecord);
} else {
changeRecord.setNewValue(attributeValue);
}
} else {
mapping.readFromRowIntoObject(row, null, object, null, query, query.getSession(), true);
}
} else if (mapping.isAggregateObjectMapping()) {
((AggregateObjectMapping) mapping).readFromReturnRowIntoObject(row, object, query, handledMappings, changeSet);
} else if (mapping.isTransformationMapping()) {
((AbstractTransformationMapping) mapping).readFromReturnRowIntoObject(row, object, query, handledMappings, changeSet);
} else {
query.getSession().log(SessionLog.FINEST, SessionLog.QUERY, "field_for_unsupported_mapping_returned", field, this.descriptor);
}
}
use of org.eclipse.persistence.internal.sessions.DirectToFieldChangeRecord in project eclipselink by eclipse-ee4j.
the class VersionLockingPolicy method updateObjectWithWriteValue.
public void updateObjectWithWriteValue(ObjectLevelModifyQuery query, Object lockValue) {
AbstractSession session = query.getSession();
Object object = query.getObject();
ObjectChangeSet objectChangeSet = query.getObjectChangeSet();
if (objectChangeSet == null) {
if (session.isUnitOfWork() && (((UnitOfWorkImpl) session).getUnitOfWorkChangeSet() != null)) {
// For aggregate collections the change set may be null, as they use the old commit still.
objectChangeSet = (ObjectChangeSet) ((UnitOfWorkImpl) session).getUnitOfWorkChangeSet().getObjectChangeSetForClone(object);
}
}
// PERF: handle normal case faster.
if (this.lockMapping != null) {
// converted to the correct (for the mapping) type lock value.
Object convertedLockValue = this.lockMapping.getObjectValue(lockValue, session);
if (objectChangeSet != null && (!objectChangeSet.isNew() || query.getDescriptor().shouldUseFullChangeSetsForNewObjects())) {
Object oldValue = this.lockMapping.getAttributeValueFromObject(object);
this.lockMapping.setAttributeValueInObject(object, convertedLockValue);
objectChangeSet.setWriteLockValue(lockValue);
// Don't use ObjectChangeSet.updateChangeRecordForAttributeWithMappedObject to avoid unnecessary conversion - convertedLockValue is already converted.
DirectToFieldChangeRecord changeRecord = new DirectToFieldChangeRecord(objectChangeSet);
changeRecord.setAttribute(this.lockMapping.getAttributeName());
changeRecord.setMapping(this.lockMapping);
changeRecord.setNewValue(convertedLockValue);
changeRecord.setOldValue(oldValue);
objectChangeSet.addChange(changeRecord);
} else {
this.lockMapping.setAttributeValueInObject(object, convertedLockValue);
}
} else {
// CR#3173211
// If the value is stored in the cache or object, there still may
// be read-only mappings for it, so the object must always be updated for
// any writable or read-only mappings for the version value.
// Reuse the method used for returning as has the same requirements.
ObjectBuilder objectBuilder = this.descriptor.getObjectBuilder();
AbstractRecord record = objectBuilder.createRecord(1, session);
record.put(this.writeLockField, lockValue);
if (objectChangeSet != null) {
objectChangeSet.setWriteLockValue(lockValue);
}
objectBuilder.assignReturnRow(object, session, record, objectChangeSet);
}
}
use of org.eclipse.persistence.internal.sessions.DirectToFieldChangeRecord in project eclipselink by eclipse-ee4j.
the class ObjectBuilder method assignSequenceNumber.
/**
* INTERNAL:
* Update the object primary key by fetching a new sequence number from the accessor.
* This assume the uses sequence numbers check has already been done.
* Adds the assigned sequence value to writeQuery's modify row.
* If object has a changeSet then sets sequence value into change set as an Id
* adds it also to object's change set in a ChangeRecord if required.
* @return the sequence value or null if not assigned.
* @exception DatabaseException - an error has occurred on the database.
*/
protected Object assignSequenceNumber(Object object, AbstractSession writeSession, WriteObjectQuery writeQuery) throws DatabaseException {
DatabaseField sequenceNumberField = this.descriptor.getSequenceNumberField();
Object existingValue = null;
if (this.sequenceMapping != null) {
existingValue = this.sequenceMapping.getAttributeValueFromObject(object);
} else {
existingValue = getBaseValueForField(sequenceNumberField, object);
}
// PERF: The (internal) support for letting the sequence decide this was removed,
// as anything other than primitive should allow null and default as such.
Object sequenceValue;
int index = this.descriptor.getPrimaryKeyFields().indexOf(sequenceNumberField);
if (isPrimaryKeyComponentInvalid(existingValue, index) || this.descriptor.getSequence().shouldAlwaysOverrideExistingValue()) {
sequenceValue = writeSession.getSequencing().getNextValue(this.descriptor.getJavaClass());
} else {
return null;
}
// Check that the value is not null, this occurs on any databases using IDENTITY type sequencing.
if (sequenceValue == null) {
return null;
}
writeSession.log(SessionLog.FINEST, SessionLog.SEQUENCING, "assign_sequence", sequenceValue, object);
Object convertedSequenceValue = null;
if (this.sequenceMapping != null) {
convertedSequenceValue = this.sequenceMapping.getObjectValue(sequenceValue, writeSession);
this.sequenceMapping.setAttributeValueInObject(object, convertedSequenceValue);
} else {
// Now add the value to the object, this gets ugly.
AbstractRecord tempRow = createRecord(1, writeSession);
tempRow.put(sequenceNumberField, sequenceValue);
// Require a query context to read into an object.
ReadObjectQuery query = new ReadObjectQuery();
query.setSession(writeSession);
DatabaseMapping mapping = getBaseMappingForField(sequenceNumberField);
Object sequenceIntoObject = getParentObjectForField(sequenceNumberField, object);
// The following method will return the converted value for the sequence.
convertedSequenceValue = mapping.readFromRowIntoObject(tempRow, null, sequenceIntoObject, null, query, writeSession, true);
}
// PERF: If PersistenceEntity is caching the primary key this must be cleared as the primary key has changed.
clearPrimaryKey(object);
if (writeQuery != null) {
Object primaryKey = extractPrimaryKeyFromObject(object, writeSession);
writeQuery.setPrimaryKey(primaryKey);
AbstractRecord modifyRow = writeQuery.getModifyRow();
// Update the row.
modifyRow.put(sequenceNumberField, sequenceValue);
if (descriptor.hasMultipleTables()) {
addPrimaryKeyForNonDefaultTable(modifyRow, object, writeSession);
}
// Update the changeSet if there is one.
if (writeSession.isUnitOfWork()) {
ObjectChangeSet objectChangeSet = writeQuery.getObjectChangeSet();
if ((objectChangeSet == null) && (((UnitOfWorkImpl) writeSession).getUnitOfWorkChangeSet() != null)) {
objectChangeSet = (ObjectChangeSet) ((UnitOfWorkImpl) writeSession).getUnitOfWorkChangeSet().getObjectChangeSetForClone(object);
}
if (objectChangeSet != null) {
// objectChangeSet.isNew() == true
if (writeQuery.getDescriptor().shouldUseFullChangeSetsForNewObjects()) {
if (this.sequenceMapping != null) {
// Don't use ObjectChangeSet.updateChangeRecordForAttribute to avoid unnecessary conversion - convertedSequenceValue is already converted.
String attributeName = this.sequenceMapping.getAttributeName();
DirectToFieldChangeRecord changeRecord = (DirectToFieldChangeRecord) objectChangeSet.getChangesForAttributeNamed(attributeName);
if (changeRecord == null) {
changeRecord = new DirectToFieldChangeRecord(objectChangeSet);
changeRecord.setAttribute(attributeName);
changeRecord.setMapping(this.sequenceMapping);
objectChangeSet.addChange(changeRecord);
}
changeRecord.setNewValue(convertedSequenceValue);
} else {
ChangeRecord changeRecord = getBaseChangeRecordForField(objectChangeSet, object, sequenceNumberField, writeSession);
if (changeRecord.getMapping().isDirectCollectionMapping()) {
// assign converted value to the attribute
((DirectToFieldChangeRecord) changeRecord).setNewValue(convertedSequenceValue);
} else if (changeRecord.getMapping().isTransformationMapping()) {
// put original (not converted) value into the record.
((TransformationMappingChangeRecord) changeRecord).getRecord().put(sequenceNumberField, sequenceValue);
}
}
}
objectChangeSet.setId(primaryKey);
}
}
}
return convertedSequenceValue;
}
Aggregations