Search in sources :

Example 96 with DatabaseRecord

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);
}
Also used : DatabaseRecord(org.eclipse.persistence.sessions.DatabaseRecord) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField)

Example 97 with DatabaseRecord

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);
                    }
                }
            }
        }
    }
}
Also used : ObjectChangeSet(org.eclipse.persistence.internal.sessions.ObjectChangeSet) Set(java.util.Set) HashSet(java.util.HashSet) DatabaseRecord(org.eclipse.persistence.sessions.DatabaseRecord) ObjectChangeSet(org.eclipse.persistence.internal.sessions.ObjectChangeSet) DeleteObjectQuery(org.eclipse.persistence.queries.DeleteObjectQuery) AbstractRecord(org.eclipse.persistence.internal.sessions.AbstractRecord) IndirectList(org.eclipse.persistence.indirection.IndirectList) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField) Iterator(java.util.Iterator) DescriptorIterator(org.eclipse.persistence.internal.descriptors.DescriptorIterator) DirectCollectionChangeRecord(org.eclipse.persistence.internal.sessions.DirectCollectionChangeRecord) List(java.util.List) IndirectList(org.eclipse.persistence.indirection.IndirectList) ArrayList(java.util.ArrayList) Map(java.util.Map) IdentityHashMap(java.util.IdentityHashMap) HashMap(java.util.HashMap)

Example 98 with DatabaseRecord

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);
    }
}
Also used : OrderedListContainerPolicy(org.eclipse.persistence.internal.queries.OrderedListContainerPolicy) ContainerPolicy(org.eclipse.persistence.internal.queries.ContainerPolicy) DatabaseRecord(org.eclipse.persistence.sessions.DatabaseRecord) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField) AbstractRecord(org.eclipse.persistence.internal.sessions.AbstractRecord)

Example 99 with DatabaseRecord

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;
}
Also used : DatabaseRecord(org.eclipse.persistence.sessions.DatabaseRecord) AbstractRecord(org.eclipse.persistence.internal.sessions.AbstractRecord)

Example 100 with DatabaseRecord

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);
}
Also used : ContainerPolicy(org.eclipse.persistence.internal.queries.ContainerPolicy) DatabaseRecord(org.eclipse.persistence.sessions.DatabaseRecord) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField) AbstractRecord(org.eclipse.persistence.internal.sessions.AbstractRecord) DataModifyQuery(org.eclipse.persistence.queries.DataModifyQuery) AbstractSession(org.eclipse.persistence.internal.sessions.AbstractSession)

Aggregations

DatabaseRecord (org.eclipse.persistence.sessions.DatabaseRecord)110 DatabaseField (org.eclipse.persistence.internal.helper.DatabaseField)44 AbstractRecord (org.eclipse.persistence.internal.sessions.AbstractRecord)43 Vector (java.util.Vector)31 ArrayList (java.util.ArrayList)17 NonSynchronizedVector (org.eclipse.persistence.internal.helper.NonSynchronizedVector)17 BigDecimal (java.math.BigDecimal)14 List (java.util.List)14 ClassDescriptor (org.eclipse.persistence.descriptors.ClassDescriptor)14 DatabaseSession (org.eclipse.persistence.sessions.DatabaseSession)14 Test (org.junit.Test)14 Expression (org.eclipse.persistence.expressions.Expression)12 AbstractSession (org.eclipse.persistence.internal.sessions.AbstractSession)12 HashMap (java.util.HashMap)11 Map (java.util.Map)10 EclipseLinkException (org.eclipse.persistence.exceptions.EclipseLinkException)7 ExpressionBuilder (org.eclipse.persistence.expressions.ExpressionBuilder)7 RelationalDescriptor (org.eclipse.persistence.descriptors.RelationalDescriptor)6 DescriptorException (org.eclipse.persistence.exceptions.DescriptorException)6 SQLUpdateStatement (org.eclipse.persistence.internal.expressions.SQLUpdateStatement)6