Search in sources :

Example 1 with CacheKeyType

use of org.eclipse.persistence.annotations.CacheKeyType in project eclipselink by eclipse-ee4j.

the class ObjectBuilder method extractPrimaryKeyFromRow.

/**
 * Extract primary key values from the specified row.
 * null is returned if the row does not contain the key.
 */
public Object extractPrimaryKeyFromRow(AbstractRecord databaseRow, AbstractSession session) {
    if (databaseRow.hasSopObject()) {
        // Entity referencing ForeignReferenceMapping has set attribute extracted from sopObject as a sopObject into a new empty row.
        return extractPrimaryKeyFromObject(databaseRow.getSopObject(), session);
    }
    List<DatabaseField> primaryKeyFields = this.descriptor.getPrimaryKeyFields();
    if (null == primaryKeyFields) {
        return null;
    }
    List<Class<?>> primaryKeyClassifications = getPrimaryKeyClassifications();
    int size = primaryKeyFields.size();
    Object[] primaryKeyValues = null;
    CacheKeyType cacheKeyType = this.descriptor.getCachePolicy().getCacheKeyType();
    if (cacheKeyType != CacheKeyType.ID_VALUE) {
        primaryKeyValues = new Object[size];
    }
    int numberOfNulls = 0;
    // PERF: use index not enumeration
    for (int index = 0; index < size; index++) {
        DatabaseField field = primaryKeyFields.get(index);
        // Ensure that the type extracted from the row is the same type as in the object.
        Class<?> classification = primaryKeyClassifications.get(index);
        Object value = databaseRow.get(field);
        if (value != null) {
            if (value.getClass() != classification) {
                value = session.getPlatform(this.descriptor.getJavaClass()).convertObject(value, classification);
            }
            if (cacheKeyType == CacheKeyType.ID_VALUE) {
                return value;
            }
            primaryKeyValues[index] = value;
        } else {
            if (this.mayHaveNullInPrimaryKey) {
                numberOfNulls++;
                if (numberOfNulls < size) {
                    primaryKeyValues[index] = null;
                } else {
                    // Must have some non null elements. If all elements are null return null.
                    return null;
                }
            } else {
                return null;
            }
        }
    }
    return new CacheId(primaryKeyValues);
}
Also used : CacheId(org.eclipse.persistence.internal.identitymaps.CacheId) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField) CacheKeyType(org.eclipse.persistence.annotations.CacheKeyType) InvalidObject(org.eclipse.persistence.internal.helper.InvalidObject)

Example 2 with CacheKeyType

use of org.eclipse.persistence.annotations.CacheKeyType in project eclipselink by eclipse-ee4j.

the class ObjectBuilder method extractPrimaryKeyFromObject.

/**
 * Extract primary key attribute values from the domainObject.
 */
public Object extractPrimaryKeyFromObject(Object domainObject, AbstractSession session, boolean shouldReturnNullIfNull) {
    if (domainObject == null) {
        return null;
    }
    // Avoid using the cached id for XML, as the relational descriptor may be different than the xml one.
    boolean isPersistenceEntity = (domainObject instanceof PersistenceEntity) && (!isXMLObjectBuilder());
    if (isPersistenceEntity) {
        Object primaryKey = ((PersistenceEntity) domainObject)._persistence_getId();
        if (primaryKey != null) {
            return primaryKey;
        }
    }
    ClassDescriptor descriptor = this.descriptor;
    boolean isNull = false;
    // Allow for inheritance, the concrete descriptor must always be used.
    if (descriptor.hasInheritance() && (domainObject.getClass() != descriptor.getJavaClass()) && (!domainObject.getClass().getSuperclass().equals(descriptor.getJavaClass()))) {
        return session.getDescriptor(domainObject).getObjectBuilder().extractPrimaryKeyFromObject(domainObject, session, shouldReturnNullIfNull);
    }
    CacheKeyType cacheKeyType = descriptor.getCachePolicy().getCacheKeyType();
    List<DatabaseField> primaryKeyFields = descriptor.getPrimaryKeyFields();
    Object[] primaryKeyValues = null;
    if (cacheKeyType != CacheKeyType.ID_VALUE) {
        primaryKeyValues = new Object[primaryKeyFields.size()];
    }
    List<DatabaseMapping> mappings = getPrimaryKeyMappings();
    int size = mappings.size();
    // PERF: optimize simple case of direct mapped singleton primary key.
    if (descriptor.hasSimplePrimaryKey()) {
        // PERF: use index not enumeration.
        for (int index = 0; index < size; index++) {
            AbstractColumnMapping mapping = (AbstractColumnMapping) mappings.get(index);
            Object keyValue = mapping.valueFromObject(domainObject, primaryKeyFields.get(index), session);
            if (isPrimaryKeyComponentInvalid(keyValue, index)) {
                if (shouldReturnNullIfNull) {
                    return null;
                }
                isNull = true;
            }
            if (cacheKeyType == CacheKeyType.ID_VALUE) {
                if (isPersistenceEntity && (!isNull)) {
                    ((PersistenceEntity) domainObject)._persistence_setId(keyValue);
                }
                return keyValue;
            } else {
                primaryKeyValues[index] = keyValue;
            }
        }
    } else {
        AbstractRecord databaseRow = createRecordForPKExtraction(size, session);
        Set<DatabaseMapping> writtenMappings = new HashSet<>(size);
        // PERF: use index not enumeration
        for (int index = 0; index < size; index++) {
            DatabaseMapping mapping = mappings.get(index);
            // Primary key mapping may be null for aggregate collection.
            if (mapping != null && !writtenMappings.contains(mapping)) {
                mapping.writeFromObjectIntoRow(domainObject, databaseRow, session, WriteType.UNDEFINED);
                writtenMappings.add(mapping);
            }
        }
        List<Class<?>> primaryKeyClassifications = getPrimaryKeyClassifications();
        Platform platform = session.getPlatform(domainObject.getClass());
        // PERF: use index not enumeration
        for (int index = 0; index < size; index++) {
            // Ensure that the type extracted from the object is the same type as in the descriptor,
            // the main reason for this is that 1-1 can optimize on vh by getting from the row as the row-type.
            Class<?> classification = primaryKeyClassifications.get(index);
            Object value = databaseRow.get(primaryKeyFields.get(index));
            if (isPrimaryKeyComponentInvalid(value, index)) {
                if (shouldReturnNullIfNull) {
                    return null;
                }
                isNull = true;
            }
            value = platform.convertObject(value, classification);
            if (cacheKeyType == CacheKeyType.ID_VALUE) {
                if (isPersistenceEntity && (!isNull)) {
                    ((PersistenceEntity) domainObject)._persistence_setId(value);
                }
                return value;
            } else {
                primaryKeyValues[index] = value;
            }
        }
    }
    CacheId id = new CacheId(primaryKeyValues);
    if (isPersistenceEntity && (!isNull)) {
        ((PersistenceEntity) domainObject)._persistence_setId(id);
    }
    return id;
}
Also used : ClassDescriptor(org.eclipse.persistence.descriptors.ClassDescriptor) Platform(org.eclipse.persistence.internal.databaseaccess.Platform) DatasourcePlatform(org.eclipse.persistence.internal.databaseaccess.DatasourcePlatform) DatabasePlatform(org.eclipse.persistence.internal.databaseaccess.DatabasePlatform) AbstractRecord(org.eclipse.persistence.internal.sessions.AbstractRecord) DatabaseMapping(org.eclipse.persistence.mappings.DatabaseMapping) AbstractColumnMapping(org.eclipse.persistence.mappings.foundation.AbstractColumnMapping) CacheId(org.eclipse.persistence.internal.identitymaps.CacheId) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField) CacheKeyType(org.eclipse.persistence.annotations.CacheKeyType) InvalidObject(org.eclipse.persistence.internal.helper.InvalidObject) IdentityHashSet(org.eclipse.persistence.internal.helper.IdentityHashSet) HashSet(java.util.HashSet)

Example 3 with CacheKeyType

use of org.eclipse.persistence.annotations.CacheKeyType in project eclipselink by eclipse-ee4j.

the class MappedKeyMapContainerPolicy 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) {
    int mapSize = pks.length / 2;
    Object result = containerInstance(mapSize);
    Object[] keys = new Object[mapSize];
    Object[] values = new Object[mapSize];
    for (int index = 0; index < pks.length; ++index) {
        keys[index / 2] = pks[index];
        ++index;
        values[index / 2] = pks[index];
    }
    List<Object> keyObjects = keyMapping.createMapComponentsFromSerializableKeyInfo(keys, session);
    if (((DatabaseMapping) valueMapping).isElementCollectionMapping()) {
        for (int i = 0; i < mapSize; i++) {
            addInto(keyObjects.get(i), values[i], result, session);
        }
    } else {
        Map<Object, Object> fromCache = session.getIdentityMapAccessorInstance().getAllFromIdentityMapWithEntityPK(values, elementDescriptor);
        List foreignKeyValues = new ArrayList(pks.length - fromCache.size());
        CacheKeyType cacheKeyType = this.elementDescriptor.getCachePolicy().getCacheKeyType();
        for (int index = 0; index < mapSize; ++index) {
            Object pk = values[index];
            if (!fromCache.containsKey(pk)) {
                if (cacheKeyType == 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(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) {
                Object pk = elementDescriptor.getObjectBuilder().extractPrimaryKeyFromObject(element, session);
                fromCache.put(pk, element);
            }
        }
        Iterator<Object> keyIterator = keyObjects.iterator();
        for (Object key : values) {
            addInto(keyIterator.next(), fromCache.get(key), result, session);
        }
    }
    return result;
}
Also used : ArrayList(java.util.ArrayList) ReadAllQuery(org.eclipse.persistence.queries.ReadAllQuery) DatabaseMapping(org.eclipse.persistence.mappings.DatabaseMapping) CacheId(org.eclipse.persistence.internal.identitymaps.CacheId) CacheKeyType(org.eclipse.persistence.annotations.CacheKeyType) ArrayList(java.util.ArrayList) List(java.util.List)

Example 4 with CacheKeyType

use of org.eclipse.persistence.annotations.CacheKeyType in project eclipselink by eclipse-ee4j.

the class OneToOneMapping method createMapComponentsFromSerializableKeyInfo.

/**
 * INTERNAL:
 * Create an instance of the Key object from the key information extracted from the map.
 * This may return the value directly in case of a simple key or will be used as the FK to load a related entity.
 */
@Override
public List<Object> createMapComponentsFromSerializableKeyInfo(Object[] keyInfo, AbstractSession session) {
    List<Object> orderedResult = new ArrayList<>(keyInfo.length);
    Map<Object, Object> fromCache = session.getIdentityMapAccessorInstance().getAllFromIdentityMapWithEntityPK(keyInfo, referenceDescriptor);
    List foreignKeyValues = new ArrayList(keyInfo.length - fromCache.size());
    CacheKeyType cacheKeyType = referenceDescriptor.getCachePolicy().getCacheKeyType();
    for (int index = 0; index < keyInfo.length; ++index) {
        Object pk = keyInfo[index];
        if (!fromCache.containsKey(pk)) {
            if (cacheKeyType == CacheKeyType.CACHE_ID) {
                foreignKeyValues.add(Arrays.asList(((CacheId) pk).getPrimaryKey()));
            } else {
                foreignKeyValues.add(pk);
            }
        }
    }
    if (!foreignKeyValues.isEmpty()) {
        ReadAllQuery query = new ReadAllQuery(referenceDescriptor.getJavaClass());
        query.setIsExecutionClone(true);
        query.addArgument(ForeignReferenceMapping.QUERY_BATCH_PARAMETER);
        query.addArgumentValue(foreignKeyValues);
        query.setSession(session);
        query.setSelectionCriteria(referenceDescriptor.buildBatchCriteriaByPK(query.getExpressionBuilder(), query));
        Collection<Object> temp = (Collection<Object>) session.executeQuery(query);
        for (Object element : temp) {
            Object pk = referenceDescriptor.getObjectBuilder().extractPrimaryKeyFromObject(element, session);
            fromCache.put(pk, element);
        }
    }
    for (Object key : keyInfo) {
        orderedResult.add(fromCache.get(key));
    }
    return orderedResult;
}
Also used : CacheKeyType(org.eclipse.persistence.annotations.CacheKeyType)

Aggregations

CacheKeyType (org.eclipse.persistence.annotations.CacheKeyType)4 CacheId (org.eclipse.persistence.internal.identitymaps.CacheId)3 DatabaseField (org.eclipse.persistence.internal.helper.DatabaseField)2 InvalidObject (org.eclipse.persistence.internal.helper.InvalidObject)2 DatabaseMapping (org.eclipse.persistence.mappings.DatabaseMapping)2 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 List (java.util.List)1 ClassDescriptor (org.eclipse.persistence.descriptors.ClassDescriptor)1 DatabasePlatform (org.eclipse.persistence.internal.databaseaccess.DatabasePlatform)1 DatasourcePlatform (org.eclipse.persistence.internal.databaseaccess.DatasourcePlatform)1 Platform (org.eclipse.persistence.internal.databaseaccess.Platform)1 IdentityHashSet (org.eclipse.persistence.internal.helper.IdentityHashSet)1 AbstractRecord (org.eclipse.persistence.internal.sessions.AbstractRecord)1 AbstractColumnMapping (org.eclipse.persistence.mappings.foundation.AbstractColumnMapping)1 ReadAllQuery (org.eclipse.persistence.queries.ReadAllQuery)1