use of org.eclipse.persistence.internal.sessions.TransformationMappingChangeRecord 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.TransformationMappingChangeRecord in project eclipselink by eclipse-ee4j.
the class AbstractTransformationMapping method internalBuildChangeRecord.
/**
* INTERNAL:
* Build a change record.
*/
public ChangeRecord internalBuildChangeRecord(Object clone, Object oldValue, ObjectChangeSet owner, AbstractSession session) {
TransformationMappingChangeRecord changeRecord = new TransformationMappingChangeRecord(owner);
changeRecord.setRow(buildPhantomRowFrom(clone, session));
changeRecord.setAttribute(getAttributeName());
changeRecord.setMapping(this);
changeRecord.setOldValue(oldValue);
return changeRecord;
}
use of org.eclipse.persistence.internal.sessions.TransformationMappingChangeRecord in project eclipselink by eclipse-ee4j.
the class AbstractTransformationMapping method updateChangeRecord.
/**
* INTERNAL:
* Either create a new change record or update the change record with the new value.
* This is used by attribute change tracking.
*/
@Override
public void updateChangeRecord(Object clone, Object newValue, Object oldValue, ObjectChangeSet objectChangeSet, UnitOfWorkImpl uow) {
TransformationMappingChangeRecord changeRecord = (TransformationMappingChangeRecord) objectChangeSet.getChangesForAttributeNamed(this.getAttributeName());
Object updatedObject = descriptor.getInstantiationPolicy().buildNewInstance();
this.setAttributeValueInObject(updatedObject, newValue);
if (!isWriteOnly()) {
if (changeRecord == null) {
objectChangeSet.addChange(internalBuildChangeRecord(updatedObject, oldValue, objectChangeSet, uow));
} else {
changeRecord.setRow(this.buildPhantomRowFrom(updatedObject, uow));
}
}
}
use of org.eclipse.persistence.internal.sessions.TransformationMappingChangeRecord 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;
}
use of org.eclipse.persistence.internal.sessions.TransformationMappingChangeRecord in project eclipselink by eclipse-ee4j.
the class AbstractTransformationMapping method readFromReturnRowIntoObject.
/**
* INTERNAL:
* Extracts value from return row and set the attribute to the value in the object.
* Return row is merged into object after execution of insert or update call
* according to ReturningPolicy.
*/
public Object readFromReturnRowIntoObject(AbstractRecord row, Object object, ReadObjectQuery query, Collection handledMappings, ObjectChangeSet changeSet) throws DatabaseException {
int size = this.fields.size();
AbstractRecord transformationRow = new DatabaseRecord(size);
for (int i = 0; i < size; i++) {
DatabaseField field = this.fields.get(i);
Object value;
if (row.containsKey(field)) {
value = row.get(field);
} else {
value = valueFromObject(object, field, query.getSession());
}
transformationRow.add(field, value);
}
if (changeSet != null && (!changeSet.isNew() || (query.getDescriptor() != null && query.getDescriptor().shouldUseFullChangeSetsForNewObjects()))) {
TransformationMappingChangeRecord record = (TransformationMappingChangeRecord) changeSet.getChangesForAttributeNamed(attributeName);
if (record == null) {
record = new TransformationMappingChangeRecord(changeSet);
record.setAttribute(attributeName);
record.setMapping(this);
record.setOldValue(getAttributeValueFromObject(object));
changeSet.addChange(record);
}
record.setRow(transformationRow);
}
Object attributeValue = readFromRowIntoObject(transformationRow, null, object, null, query, query.getSession(), true);
if (handledMappings != null) {
handledMappings.add(this);
}
return attributeValue;
}
Aggregations