use of org.eclipse.persistence.sessions.DatabaseRecord in project eclipselink by eclipse-ee4j.
the class ObjectBuilder method cacheForeignKeyValues.
/**
* INTERNAL:
* This method is used to store the FK values used for this mapping in the cachekey.
* This is used when the mapping is protected but we have retrieved the fk values and will cache
* them for use when the entity is cloned.
*/
public void cacheForeignKeyValues(Object source, CacheKey cacheKey, ClassDescriptor descriptor, AbstractSession session) {
Set<DatabaseField> foreignKeys = this.descriptor.getForeignKeyValuesForCaching();
if (foreignKeys.isEmpty()) {
return;
}
DatabaseRecord cacheRecord = new DatabaseRecord(foreignKeys.size());
for (DatabaseField field : foreignKeys) {
cacheRecord.put(field, extractValueFromObjectForField(source, field, session));
}
cacheKey.setProtectedForeignKeys(cacheRecord);
}
use of org.eclipse.persistence.sessions.DatabaseRecord in project eclipselink by eclipse-ee4j.
the class DirectCollectionMapping method postUpdateWithChangeSetListOrder.
/**
* INTERNAL:
* Update private owned part.
*/
protected void postUpdateWithChangeSetListOrder(WriteObjectQuery writeQuery) throws DatabaseException {
ObjectChangeSet changeSet = writeQuery.getObjectChangeSet();
DirectCollectionChangeRecord changeRecord = (DirectCollectionChangeRecord) changeSet.getChangesForAttributeNamed(this.getAttributeName());
if (changeRecord == null) {
return;
}
for (int index = 0; index < getReferenceKeyFields().size(); index++) {
DatabaseField referenceKey = getReferenceKeyFields().get(index);
DatabaseField sourceKey = getSourceKeyFields().get(index);
Object sourceKeyValue = writeQuery.getTranslationRow().get(sourceKey);
writeQuery.getTranslationRow().put(referenceKey, sourceKeyValue);
}
boolean shouldRepairOrder = false;
if (changeRecord.getLatestCollection() instanceof IndirectList) {
shouldRepairOrder = ((IndirectList) changeRecord.getLatestCollection()).isListOrderBrokenInDb();
}
if (shouldRepairOrder) {
// delete all members of collection
DeleteObjectQuery deleteQuery = new DeleteObjectQuery();
deleteQuery.setObject(writeQuery.getObject());
deleteQuery.setSession(writeQuery.getSession());
deleteQuery.setTranslationRow(writeQuery.getTranslationRow());
// Hey I might actually want to use an inner class here... ok array for now.
Object[] eventDeleteAll = new Object[2];
eventDeleteAll[0] = DeleteAll;
eventDeleteAll[1] = deleteQuery;
writeQuery.getSession().getCommitManager().addDataModificationEvent(this, eventDeleteAll);
// re-insert them back
for (int i = 0; i < ((List) changeRecord.getLatestCollection()).size(); i++) {
Object value = ((List) changeRecord.getLatestCollection()).get(i);
value = getFieldValue(value, writeQuery.getSession());
AbstractRecord insertRow = writeQuery.getTranslationRow().clone();
insertRow.add(getDirectField(), value);
insertRow.add(this.listOrderField, i);
// Hey I might actually want to use an inner class here... ok array for now.
Object[] event = new Object[3];
event[0] = Insert;
event[1] = getInsertQuery();
event[2] = insertRow;
writeQuery.getSession().getCommitManager().addDataModificationEvent(this, event);
}
((IndirectList) changeRecord.getLatestCollection()).setIsListOrderBrokenInDb(false);
changeRecord.setOrderHasBeenRepaired(true);
return;
}
if (changeRecord.getChangedIndexes() == null) {
compareListsForChange((List) changeRecord.getOriginalCollection(), (List) changeRecord.getLatestCollection(), changeRecord, writeQuery.getSession());
}
Iterator<Map.Entry<Object, Set[]>> it = changeRecord.getChangedIndexes().entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Object, Set[]> entry = it.next();
Object value = entry.getKey();
if (getValueConverter() != null) {
value = getValueConverter().convertObjectValueToDataValue(value, writeQuery.getSession());
}
Set[] indexes = entry.getValue();
Set indexesBefore = indexes[0];
Set indexesAfter = indexes[1];
if (indexesAfter == null) {
// All copies of the target object deleted - don't need to verify order field contents.
AbstractRecord deleteRow = writeQuery.getTranslationRow().clone();
// Hey I might actually want to use an inner class here... ok array for now.
Object[] event = new Object[3];
event[0] = Delete;
if (value == null) {
// Bug 306075 - for deleting a null value from a collection
event[1] = getDeleteNullQuery();
} else {
deleteRow.add(getDirectField(), value);
event[1] = getDeleteQuery();
}
event[2] = deleteRow;
writeQuery.getSession().getCommitManager().addDataModificationEvent(this, event);
} else if (indexesAfter.isEmpty()) {
// Some copies of the target objects should be deleted, some left in the db
Iterator<Integer> itBefore = indexesBefore.iterator();
while (itBefore.hasNext()) {
AbstractRecord deleteAtIndexRow = writeQuery.getTranslationRow().clone();
deleteAtIndexRow.add(getDirectField(), value);
deleteAtIndexRow.add(this.listOrderField, itBefore.next());
// Hey I might actually want to use an inner class here... ok array for now.
Object[] event = new Object[3];
event[0] = DeleteAtIndex;
event[1] = deleteAtIndexQuery;
event[2] = deleteAtIndexRow;
writeQuery.getSession().getCommitManager().addDataModificationEvent(this, event);
}
} else {
if (indexesBefore == null || indexesBefore.isEmpty()) {
// insert the object for each index in indexesAfter
Iterator<Integer> itAfter = indexesAfter.iterator();
while (itAfter.hasNext()) {
AbstractRecord insertRow = writeQuery.getTranslationRow().clone();
insertRow.add(getDirectField(), value);
insertRow.add(this.listOrderField, itAfter.next());
// Hey I might actually want to use an inner class here... ok array for now.
Object[] event = new Object[3];
event[0] = Insert;
event[1] = getInsertQuery();
event[2] = insertRow;
writeQuery.getSession().getCommitManager().addDataModificationEvent(this, event);
}
} else {
Iterator<Integer> itBefore = indexesBefore.iterator();
Iterator<Integer> itAfter = indexesAfter.iterator();
while (itBefore.hasNext() || itAfter.hasNext()) {
if (itBefore.hasNext()) {
if (itAfter.hasNext()) {
// update the object changing index from indexBefore to indexAfter
AbstractRecord updateAtIndexRow = writeQuery.getTranslationRow().clone();
updateAtIndexRow.add(getDirectField(), value);
updateAtIndexRow.add(this.listOrderField, itBefore.next());
// Hey I might actually want to use an inner class here... ok array for now.
Object[] event = new Object[4];
event[0] = UpdateAtIndex;
event[1] = updateAtIndexQuery;
event[2] = updateAtIndexRow;
DatabaseRecord modifyRow = new DatabaseRecord(1);
modifyRow.add(this.listOrderField, itAfter.next());
event[3] = modifyRow;
writeQuery.getSession().getCommitManager().addDataModificationEvent(this, event);
} else {
// delete the object at indexBefore
AbstractRecord deleteAtIndexRow = writeQuery.getTranslationRow().clone();
deleteAtIndexRow.add(getDirectField(), value);
deleteAtIndexRow.add(this.listOrderField, itBefore.next());
// Hey I might actually want to use an inner class here... ok array for now.
Object[] event = new Object[3];
event[0] = DeleteAtIndex;
event[1] = deleteAtIndexQuery;
event[2] = deleteAtIndexRow;
writeQuery.getSession().getCommitManager().addDataModificationEvent(this, event);
}
} else {
// itAfter.hasNext() must be true
// insert the object at indexAfter
AbstractRecord insertRow = writeQuery.getTranslationRow().clone();
insertRow.add(getDirectField(), value);
insertRow.add(this.listOrderField, itAfter.next());
// Hey I might actually want to use an inner class here... ok array for now.
Object[] event = new Object[3];
event[0] = Insert;
event[1] = getInsertQuery();
event[2] = insertRow;
writeQuery.getSession().getCommitManager().addDataModificationEvent(this, event);
}
}
}
}
}
}
use of org.eclipse.persistence.sessions.DatabaseRecord in project eclipselink by eclipse-ee4j.
the class DirectCollectionMapping method postInsert.
/**
* INTERNAL:
* Insert the private owned object.
*/
@Override
public void postInsert(WriteObjectQuery query) throws DatabaseException {
Object objects;
AbstractRecord databaseRow = new DatabaseRecord();
if (isReadOnly()) {
return;
}
objects = getRealCollectionAttributeValueFromObject(query.getObject(), query.getSession());
ContainerPolicy containerPolicy = getContainerPolicy();
if (containerPolicy.isEmpty(objects)) {
return;
}
prepareTranslationRow(query.getTranslationRow(), query.getObject(), query.getDescriptor(), query.getSession());
// Extract primary key and value from the source.
for (int index = 0; index < getReferenceKeyFields().size(); index++) {
DatabaseField referenceKey = getReferenceKeyFields().get(index);
DatabaseField sourceKey = getSourceKeyFields().get(index);
Object sourceKeyValue = query.getTranslationRow().get(sourceKey);
databaseRow.put(referenceKey, sourceKeyValue);
}
int orderIndex = 0;
// Extract target field and its value. Construct insert statement and execute it
for (Object iter = containerPolicy.iteratorFor(objects); containerPolicy.hasNext(iter); ) {
Object wrappedObject = containerPolicy.nextEntry(iter, query.getSession());
Object object = containerPolicy.unwrapIteratorResult(wrappedObject);
if (getValueConverter() != null) {
object = getValueConverter().convertObjectValueToDataValue(object, query.getSession());
}
databaseRow.put(getDirectField(), object);
// In the uow data queries are cached until the end of the commit.
if (query.shouldCascadeOnlyDependentParts()) {
// Hey I might actually want to use an inner class here... ok array for now.
Object[] event = new Object[3];
event[0] = Insert;
event[1] = getInsertQuery();
event[2] = databaseRow.clone();
if (listOrderField != null) {
((AbstractRecord) event[2]).put(listOrderField, orderIndex++);
}
query.getSession().getCommitManager().addDataModificationEvent(this, event);
} else {
query.getSession().executeQuery(getInsertQuery(), databaseRow);
if ((getHistoryPolicy() != null) && getHistoryPolicy().shouldHandleWrites()) {
getHistoryPolicy().mappingLogicalInsert(getInsertQuery(), databaseRow, query.getSession());
}
}
containerPolicy.propogatePostInsert(query, wrappedObject);
}
}
use of org.eclipse.persistence.sessions.DatabaseRecord in project eclipselink by eclipse-ee4j.
the class OneToManyMapping method createModifyRowForAddTargetQuery.
/**
* INTERNAL:
*/
protected AbstractRecord createModifyRowForAddTargetQuery() {
AbstractRecord modifyRow = new DatabaseRecord();
containerPolicy.addFieldsForMapKey(modifyRow);
if (listOrderField != null) {
modifyRow.add(listOrderField, null);
}
return modifyRow;
}
use of org.eclipse.persistence.sessions.DatabaseRecord in project eclipselink by eclipse-ee4j.
the class OneToManyMapping method updateTargetForeignKeyPostUpdateSource_ObjectRemoved.
/**
* INTERNAL:
* Update target foreign key after a target object was removed from the source. This follows following steps.
* <p>- Extract primary key and its value from the source object.
* <p>- Extract target key and its value from the target object.
* <p>- Construct an update statement with above fields and values for target table.
* <p>- execute the statement.
*/
public void updateTargetForeignKeyPostUpdateSource_ObjectRemoved(ObjectLevelModifyQuery query, Object objectRemoved) throws DatabaseException {
if (this.isReadOnly) {
return;
}
AbstractSession session = query.getSession();
prepareTranslationRow(query.getTranslationRow(), query.getObject(), query.getDescriptor(), session);
AbstractRecord translationRow = new DatabaseRecord();
// Extract primary key and value from the source (use translation row).
int size = this.sourceKeyFields.size();
AbstractRecord modifyRow = new DatabaseRecord(size);
for (int index = 0; index < size; index++) {
DatabaseField sourceKey = this.sourceKeyFields.get(index);
DatabaseField targetForeignKey = this.targetForeignKeyFields.get(index);
Object sourceKeyValue = query.getTranslationRow().get(sourceKey);
translationRow.add(targetForeignKey, sourceKeyValue);
// Need to set this value to null in the modify row.
modifyRow.add(targetForeignKey, null);
}
if (listOrderField != null) {
modifyRow.add(listOrderField, null);
}
ContainerPolicy cp = getContainerPolicy();
// Extract target field and its value from the object.
size = targetPrimaryKeyFields.size();
for (int index = 0; index < size; index++) {
DatabaseField targetPrimaryKey = targetPrimaryKeyFields.get(index);
Object targetKeyValue = getReferenceDescriptor().getObjectBuilder().extractValueFromObjectForField(cp.unwrapIteratorResult(objectRemoved), targetPrimaryKey, session);
translationRow.add(targetPrimaryKey, targetKeyValue);
}
// Need a different modify row than translation row, as the same field has different values in each.
DataModifyQuery removeQuery = (DataModifyQuery) this.removeTargetQuery.clone();
removeQuery.setModifyRow(modifyRow);
removeQuery.setHasModifyRow(true);
removeQuery.setIsExecutionClone(true);
session.executeQuery(removeQuery, translationRow);
}
Aggregations