Search in sources :

Example 11 with CacheId

use of org.eclipse.persistence.internal.identitymaps.CacheId in project eclipselink by eclipse-ee4j.

the class AggregateCollectionMapping method extractBatchKeyFromRow.

/**
 * INTERNAL:
 * Extract the primary key value from the source row.
 * Used for batch reading, most following same order and fields as in the mapping.
 */
@Override
protected Object extractBatchKeyFromRow(AbstractRecord row, AbstractSession session) {
    int size = this.sourceKeyFields.size();
    Object[] key = new Object[size];
    ConversionManager conversionManager = session.getDatasourcePlatform().getConversionManager();
    for (int index = 0; index < size; index++) {
        DatabaseField field = this.sourceKeyFields.get(index);
        Object value = row.get(field);
        // Must ensure the classification gets a cache hit.
        try {
            value = conversionManager.convertObject(value, field.getType());
        } catch (ConversionException exception) {
            throw ConversionException.couldNotBeConverted(this, this.descriptor, exception);
        }
        key[index] = value;
    }
    return new CacheId(key);
}
Also used : ConversionException(org.eclipse.persistence.exceptions.ConversionException) CacheId(org.eclipse.persistence.internal.identitymaps.CacheId) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField) ConversionManager(org.eclipse.persistence.internal.helper.ConversionManager)

Example 12 with CacheId

use of org.eclipse.persistence.internal.identitymaps.CacheId in project eclipselink by eclipse-ee4j.

the class AggregateCollectionMapping method extractKeyFromTargetRow.

/**
 * INTERNAL:
 * Extract the source primary key value from the target row.
 * Used for batch reading, most following same order and fields as in the mapping.
 */
@Override
protected Object extractKeyFromTargetRow(AbstractRecord row, AbstractSession session) {
    int size = this.targetForeignKeyFields.size();
    Object[] key = new Object[size];
    ConversionManager conversionManager = session.getDatasourcePlatform().getConversionManager();
    for (int index = 0; index < size; index++) {
        DatabaseField targetField = this.targetForeignKeyFields.get(index);
        DatabaseField sourceField = this.sourceKeyFields.get(index);
        Object value = row.get(targetField);
        // Must ensure the classification gets a cache hit.
        try {
            value = conversionManager.convertObject(value, sourceField.getType());
        } catch (ConversionException e) {
            throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
        }
        key[index] = value;
    }
    return new CacheId(key);
}
Also used : ConversionException(org.eclipse.persistence.exceptions.ConversionException) CacheId(org.eclipse.persistence.internal.identitymaps.CacheId) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField) ConversionManager(org.eclipse.persistence.internal.helper.ConversionManager)

Example 13 with CacheId

use of org.eclipse.persistence.internal.identitymaps.CacheId in project eclipselink by eclipse-ee4j.

the class AggregateCollectionMapping method compareListsAndWrite_NonUpdatableListOrderField.

/**
 * INTERNAL:
 * Old and new lists are compared and only the changes are written to the database.
 * Called only if listOrderField != null
 */
protected void compareListsAndWrite_NonUpdatableListOrderField(List previousList, List currentList, WriteObjectQuery query) throws DatabaseException, OptimisticLockException {
    boolean shouldRepairOrder = false;
    if (currentList instanceof IndirectList) {
        shouldRepairOrder = ((IndirectList) currentList).isListOrderBrokenInDb();
    }
    HashMap<Object, Object[]> previousAndCurrentByKey = new HashMap<>();
    int pkSize = getReferenceDescriptor().getPrimaryKeyFields().size();
    // First index the current objects by their primary key.
    for (int i = 0; i < currentList.size(); i++) {
        Object currentObject = currentList.get(i);
        try {
            CacheId primaryKey = (CacheId) getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(currentObject, query.getSession());
            primaryKey.add(i);
            Object[] previousAndCurrent = new Object[] { null, currentObject };
            previousAndCurrentByKey.put(primaryKey, previousAndCurrent);
        } catch (NullPointerException e) {
            // ideally the customer should check for these themselves.
            if (currentObject != null) {
                throw e;
            }
        }
    }
    if (shouldRepairOrder) {
        DeleteAllQuery deleteAllQuery = (DeleteAllQuery) this.deleteAllQuery;
        if (this.isCascadeOnDeleteSetOnDatabase) {
            deleteAllQuery = (DeleteAllQuery) deleteAllQuery.clone();
            deleteAllQuery.setIsInMemoryOnly(false);
        }
        deleteAllQuery.executeDeleteAll(query.getSession().getSessionForClass(getReferenceClass()), query.getTranslationRow(), new Vector(previousList));
    } else {
        // Next index the previous objects (read from db or from backup in uow)
        for (int i = 0; i < previousList.size(); i++) {
            Object previousObject = previousList.get(i);
            CacheId primaryKey = (CacheId) getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(previousObject, query.getSession());
            primaryKey.add(i);
            Object[] previousAndCurrent = previousAndCurrentByKey.get(primaryKey);
            if (previousAndCurrent == null) {
                // there's no current object - that means that previous object should be deleted
                DatabaseRecord extraData = new DatabaseRecord(1);
                extraData.put(this.listOrderField, i);
                objectRemovedDuringUpdate(query, previousObject, extraData);
            } else {
                previousAndCurrent[0] = previousObject;
            }
        }
    }
    Iterator<Map.Entry<Object, Object[]>> it = previousAndCurrentByKey.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry<Object, Object[]> entry = it.next();
        Object key = entry.getKey();
        Object[] previousAndCurrent = entry.getValue();
        // previousObject may be null, meaning currentObject has been added to the list
        Object previousObject = previousAndCurrent[0];
        // currentObject is not null
        Object currentObject = previousAndCurrent[1];
        if (previousObject == null) {
            // there's no previous object - that means that current object should be added.
            // index of currentObject in currentList
            int iCurrent = (Integer) ((CacheId) key).getPrimaryKey()[pkSize];
            DatabaseRecord extraData = new DatabaseRecord(1);
            extraData.put(this.listOrderField, iCurrent);
            objectAddedDuringUpdate(query, currentObject, null, extraData);
        } else {
            if (!this.isEntireObjectPK) {
                objectUnchangedDuringUpdate(query, currentObject, previousObject);
            }
        }
    }
    if (shouldRepairOrder) {
        ((IndirectList) currentList).setIsListOrderBrokenInDb(false);
    }
}
Also used : DeleteAllQuery(org.eclipse.persistence.queries.DeleteAllQuery) DatabaseRecord(org.eclipse.persistence.sessions.DatabaseRecord) HashMap(java.util.HashMap) IndirectList(org.eclipse.persistence.indirection.IndirectList) CacheId(org.eclipse.persistence.internal.identitymaps.CacheId) Vector(java.util.Vector) NonSynchronizedVector(org.eclipse.persistence.internal.helper.NonSynchronizedVector) Map(java.util.Map) HashMap(java.util.HashMap) TreeMap(java.util.TreeMap)

Example 14 with CacheId

use of org.eclipse.persistence.internal.identitymaps.CacheId in project eclipselink by eclipse-ee4j.

the class ContainerPolicy method valueFromPKList.

/**
 * INTERNAL:
 * This method is used to load a relationship from a list of PKs. This list
 * may be available if the relationship has been cached.
 */
public Object valueFromPKList(Object[] pks, AbstractRecord foreignKeys, ForeignReferenceMapping mapping, AbstractSession session) {
    Object result = containerInstance(pks.length);
    Map<Object, Object> fromCache = session.getIdentityMapAccessorInstance().getAllFromIdentityMapWithEntityPK(pks, elementDescriptor);
    for (Object entity : fromCache.values()) {
        addInto(entity, result, session);
    }
    List foreignKeyValues = new ArrayList(pks.length - fromCache.size());
    for (int index = 0; index < pks.length; ++index) {
        Object pk = pks[index];
        if (!fromCache.containsKey(pk)) {
            if (this.elementDescriptor.getCachePolicy().getCacheKeyType() == CacheKeyType.CACHE_ID) {
                foreignKeyValues.add(Arrays.asList(((CacheId) pk).getPrimaryKey()));
            } else {
                foreignKeyValues.add(pk);
            }
        }
    }
    if (!foreignKeyValues.isEmpty()) {
        if (foreignKeyValues.size() == pks.length) {
            // need to find all of the entities so just perform a FK search
            return session.executeQuery(mapping.getSelectionQuery(), foreignKeys);
        }
        ReadAllQuery query = new ReadAllQuery();
        query.setReferenceClass(elementDescriptor.getJavaClass());
        query.setIsExecutionClone(true);
        query.addArgument(ForeignReferenceMapping.QUERY_BATCH_PARAMETER);
        query.setSession(session);
        query.setSelectionCriteria(elementDescriptor.buildBatchCriteriaByPK(query.getExpressionBuilder(), query));
        int pkCount = foreignKeyValues.size();
        Collection<Object> temp = new ArrayList<>();
        List arguments = new ArrayList();
        arguments.add(foreignKeyValues);
        if (pkCount > 1000) {
            int index = 0;
            while (index + 1000 < pkCount) {
                // some databases only support ins < 1000 entries
                List pkList = new ArrayList();
                pkList.addAll(foreignKeyValues.subList(index, index + 1000));
                arguments.set(0, pkList);
                query.setArgumentValues(arguments);
                temp.addAll((Collection<Object>) session.executeQuery(query));
                index += 1000;
            }
            foreignKeyValues = foreignKeyValues.subList(index, pkCount);
        }
        arguments.set(0, foreignKeyValues);
        query.setArgumentValues(arguments);
        // need to put the translation row here or it will be replaced later.
        temp.addAll((Collection<Object>) session.executeQuery(query));
        if (temp.size() < pkCount) {
            // element.  Execute a reload based on FK.
            return session.executeQuery(mapping.getSelectionQuery(), foreignKeys);
        }
        for (Object element : temp) {
            addInto(element, result, session);
        }
    }
    return result;
}
Also used : CacheId(org.eclipse.persistence.internal.identitymaps.CacheId) ArrayList(java.util.ArrayList) ReadAllQuery(org.eclipse.persistence.queries.ReadAllQuery) List(java.util.List) ArrayList(java.util.ArrayList)

Example 15 with CacheId

use of org.eclipse.persistence.internal.identitymaps.CacheId in project eclipselink by eclipse-ee4j.

the class ListContainerPolicy method valueFromPKList.

/**
 * INTERNAL:
 * This method is used to load a relationship from a list of PKs. This list
 * may be available if the relationship has been cached.
 */
@Override
public Object valueFromPKList(Object[] pks, AbstractRecord foreignKeys, ForeignReferenceMapping mapping, AbstractSession session) {
    Object result = containerInstance(pks.length);
    Map<Object, Object> fromCache = session.getIdentityMapAccessorInstance().getAllFromIdentityMapWithEntityPK(pks, elementDescriptor);
    List foreignKeyValues = new ArrayList(pks.length - fromCache.size());
    for (int index = 0; index < pks.length; ++index) {
        // it is a map so the keys are in the list but we do not need them in this case
        Object pk = pks[index];
        if (!fromCache.containsKey(pk)) {
            if (this.elementDescriptor.getCachePolicy().getCacheKeyType() == CacheKeyType.CACHE_ID) {
                foreignKeyValues.add(Arrays.asList(((CacheId) pk).getPrimaryKey()));
            } else {
                foreignKeyValues.add(pk);
            }
        }
    }
    if (!foreignKeyValues.isEmpty()) {
        if (foreignKeyValues.size() == pks.length) {
            // need to find all of the entities so just perform a FK search
            return session.executeQuery(mapping.getSelectionQuery(), foreignKeys);
        }
        ReadAllQuery query = new ReadAllQuery();
        query.setReferenceClass(this.elementDescriptor.getJavaClass());
        query.setIsExecutionClone(true);
        query.setSession(session);
        query.addArgument(ForeignReferenceMapping.QUERY_BATCH_PARAMETER);
        query.setSelectionCriteria(elementDescriptor.buildBatchCriteriaByPK(query.getExpressionBuilder(), query));
        int pkCount = foreignKeyValues.size();
        Collection<Object> temp = new ArrayList<>();
        List arguments = new ArrayList();
        arguments.add(foreignKeyValues);
        if (pkCount > 1000) {
            int index = 0;
            while (index + 1000 < pkCount) {
                // some databases only support ins < 1000 entries
                List pkList = new ArrayList();
                pkList.addAll(foreignKeyValues.subList(index, index + 1000));
                arguments.set(0, pkList);
                query.setArgumentValues(arguments);
                temp.addAll((Collection<Object>) session.executeQuery(query));
                index += 1000;
            }
            foreignKeyValues = foreignKeyValues.subList(index, pkCount);
        }
        arguments.set(0, foreignKeyValues);
        query.setArgumentValues(arguments);
        // need to put the translation row here or it will be replaced later.
        temp.addAll((Collection<Object>) session.executeQuery(query));
        if (temp.size() < pkCount) {
            // element.  Execute a reload based on FK.
            return session.executeQuery(mapping.getSelectionQuery(), foreignKeys);
        }
        for (Object element : temp) {
            Object pk = elementDescriptor.getObjectBuilder().extractPrimaryKeyFromObject(element, session);
            fromCache.put(pk, element);
        }
    }
    for (Object key : pks) {
        addInto(fromCache.get(key), result, session);
    }
    return result;
}
Also used : CacheId(org.eclipse.persistence.internal.identitymaps.CacheId) ArrayList(java.util.ArrayList) ReadAllQuery(org.eclipse.persistence.queries.ReadAllQuery) ArrayList(java.util.ArrayList) List(java.util.List)

Aggregations

CacheId (org.eclipse.persistence.internal.identitymaps.CacheId)38 DatabaseField (org.eclipse.persistence.internal.helper.DatabaseField)19 ArrayList (java.util.ArrayList)12 List (java.util.List)10 ClassDescriptor (org.eclipse.persistence.descriptors.ClassDescriptor)8 ConversionException (org.eclipse.persistence.exceptions.ConversionException)8 ConversionManager (org.eclipse.persistence.internal.helper.ConversionManager)8 CacheKey (org.eclipse.persistence.internal.identitymaps.CacheKey)5 DatabaseMapping (org.eclipse.persistence.mappings.DatabaseMapping)5 HashMap (java.util.HashMap)4 AbstractRecord (org.eclipse.persistence.internal.sessions.AbstractRecord)4 XMLField (org.eclipse.persistence.oxm.XMLField)4 Vector (java.util.Vector)3 CacheKeyType (org.eclipse.persistence.annotations.CacheKeyType)3 CoreDescriptor (org.eclipse.persistence.core.descriptors.CoreDescriptor)3 InvalidObject (org.eclipse.persistence.internal.helper.InvalidObject)3 Descriptor (org.eclipse.persistence.internal.oxm.mappings.Descriptor)3 ReadAllQuery (org.eclipse.persistence.queries.ReadAllQuery)3 SAXException (org.xml.sax.SAXException)3 SAXParseException (org.xml.sax.SAXParseException)3