Search in sources :

Example 6 with CacheId

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

the class ForeignReferenceMapping method extractResultFromBatchQuery.

/**
 * INTERNAL:
 * Extract the value from the batch optimized query, this should be supported by most query types.
 */
public Object extractResultFromBatchQuery(ReadQuery batchQuery, CacheKey parentCacheKey, AbstractRecord sourceRow, AbstractSession session, ObjectLevelReadQuery originalQuery) throws QueryException {
    Map<Object, Object> batchedObjects;
    Object result;
    Object sourceKey = extractBatchKeyFromRow(sourceRow, session);
    if (sourceKey == null) {
        // If the foreign key was null, then just return null.
        return null;
    }
    Object cachedObject = checkCacheForBatchKey(sourceRow, sourceKey, null, batchQuery, originalQuery, session);
    if (cachedObject != null) {
        // If the object is already in the cache, then just return it.
        return cachedObject;
    }
    // Ensure the query is only executed once.
    synchronized (batchQuery) {
        // Check if query was already executed.
        batchedObjects = batchQuery.getBatchObjects();
        BatchFetchPolicy originalPolicy = originalQuery.getBatchFetchPolicy();
        if (batchedObjects == null) {
            batchedObjects = new Hashtable<>();
            batchQuery.setBatchObjects(batchedObjects);
        } else {
            result = batchedObjects.get(sourceKey);
            if (result == Helper.NULL_VALUE) {
                return null;
            // If IN may not have that batch yet, or it may have been null.
            } else if ((result != null) || (!originalPolicy.isIN())) {
                return result;
            }
        }
        // In case of IN the batch including this row may not have been executed yet.
        AbstractRecord translationRow = originalQuery.getTranslationRow();
        if (translationRow == null) {
            translationRow = new DatabaseRecord();
        }
        // Execute query and index resulting object sets by key.
        if (originalPolicy.isIN()) {
            // Need to extract all foreign key values from all parent rows for IN parameter.
            List<AbstractRecord> parentRows = originalPolicy.getDataResults(this);
            // Execute queries by batch if too many rows.
            int rowsSize = parentRows.size();
            int size = Math.min(rowsSize, originalPolicy.getSize());
            if (size == 0) {
                return null;
            }
            int startIndex = 0;
            if (size != rowsSize) {
                // If only fetching a page, need to make sure the row we want is in the page.
                startIndex = parentRows.indexOf(sourceRow);
            }
            if (startIndex == -1) {
                return null;
            }
            List foreignKeyValues = new ArrayList(size);
            Set foreignKeys = new HashSet(size);
            int index = 0;
            int offset = startIndex;
            for (int count = 0; count < size; count++) {
                if (index >= rowsSize) {
                    // Processed all rows, done.
                    break;
                } else if ((offset + index) >= rowsSize) {
                    // If passed the end, go back to start.
                    offset = index * -1;
                }
                AbstractRecord row = parentRows.get(offset + index);
                // result of duplicate filtering being true for constructing the ComplexQueryResult
                if (row != null) {
                    Object foreignKey = extractBatchKeyFromRow(row, session);
                    if (foreignKey == null) {
                        // Ignore null foreign keys.
                        count--;
                    } else {
                        cachedObject = checkCacheForBatchKey(row, foreignKey, batchedObjects, batchQuery, originalQuery, session);
                        if (cachedObject != null) {
                            // Avoid fetching things a cache hit occurs for.
                            count--;
                        } else {
                            // Ensure the same id is not selected twice.
                            if (foreignKeys.contains(foreignKey)) {
                                count--;
                            } else {
                                Object[] key = ((CacheId) foreignKey).getPrimaryKey();
                                Object foreignKeyValue = key[0];
                                // Support composite keys using nested IN.
                                if (key.length > 1) {
                                    foreignKeyValue = Arrays.asList(key);
                                }
                                foreignKeyValues.add(foreignKeyValue);
                                foreignKeys.add(foreignKey);
                            }
                        }
                    }
                }
                index++;
            }
            // Need to compute remaining rows, this is tricky because a page in the middle could have been processed.
            List<AbstractRecord> remainingParentRows;
            if (startIndex == 0) {
                // Tail
                remainingParentRows = new ArrayList<>(parentRows.subList(index, rowsSize));
            } else if (startIndex == offset) {
                // Head and tail.
                remainingParentRows = new ArrayList<>(parentRows.subList(0, startIndex));
                remainingParentRows.addAll(parentRows.subList(startIndex + index, rowsSize));
            } else {
                // Middle
                remainingParentRows = new ArrayList<>(parentRows.subList(offset + index, startIndex));
            }
            originalPolicy.setDataResults(this, remainingParentRows);
            translationRow = translationRow.clone();
            translationRow.put(QUERY_BATCH_PARAMETER, foreignKeyValues);
            // Register each id as null, in case it has no relationship.
            for (Object foreignKey : foreignKeys) {
                batchedObjects.put(foreignKey, Helper.NULL_VALUE);
            }
        } else if (batchQuery.isReadAllQuery() && ((ReadAllQuery) batchQuery).getBatchFetchPolicy().isIN()) {
            throw QueryException.originalQueryMustUseBatchIN(this, originalQuery);
        }
        executeBatchQuery(batchQuery, parentCacheKey, batchedObjects, session, translationRow);
        batchQuery.setSession(null);
    }
    result = batchedObjects.get(sourceKey);
    if (result == Helper.NULL_VALUE) {
        return null;
    } else {
        return result;
    }
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) UnitOfWorkChangeSet(org.eclipse.persistence.internal.sessions.UnitOfWorkChangeSet) DatabaseRecord(org.eclipse.persistence.sessions.DatabaseRecord) AbstractRecord(org.eclipse.persistence.internal.sessions.AbstractRecord) ArrayList(java.util.ArrayList) CacheId(org.eclipse.persistence.internal.identitymaps.CacheId) BatchFetchPolicy(org.eclipse.persistence.queries.BatchFetchPolicy) List(java.util.List) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet)

Example 7 with CacheId

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

the class CachePolicy method checkCacheByIndex.

/**
 * INTERNAL:
 * Lookup the expression in the cache if it contains any indexes.
 */
public CacheKey checkCacheByIndex(Expression expression, AbstractRecord translationRow, ClassDescriptor descriptor, AbstractSession session) {
    if (!hasCacheIndexes()) {
        return null;
    }
    AbstractRecord record = descriptor.getObjectBuilder().extractRowFromExpression(expression, translationRow, session);
    if (record == null) {
        return null;
    }
    for (CacheIndex index : this.cacheIndexes.values()) {
        List<DatabaseField> fields = index.getFields();
        int size = fields.size();
        Object[] values = new Object[size];
        for (int count = 0; count < size; count++) {
            Object value = record.get(fields.get(count));
            if (value == null) {
                break;
            }
            values[count] = value;
        }
        CacheId indexValues = new CacheId(values);
        CacheKey cacheKey = session.getIdentityMapAccessorInstance().getCacheKeyByIndex(index, indexValues, true, descriptor);
        if (cacheKey != null) {
            return cacheKey;
        }
    }
    return null;
}
Also used : CacheId(org.eclipse.persistence.internal.identitymaps.CacheId) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField) AbstractRecord(org.eclipse.persistence.internal.sessions.AbstractRecord) CacheKey(org.eclipse.persistence.internal.identitymaps.CacheKey)

Example 8 with CacheId

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

the class XMLObjectBuilder method buildRow.

/**
 * Build the nested row into the parent dom.
 */
public AbstractRecord buildRow(Object object, AbstractSession session, DatabaseField xmlField, XMLRecord parentRecord) {
    if (isXmlDescriptor() && ((Descriptor) getDescriptor()).shouldPreserveDocument()) {
        Object pk = extractPrimaryKeyFromObject(object, session);
        if ((pk == null) || (pk instanceof CacheId) && (((CacheId) pk).getPrimaryKey().length == 0)) {
            pk = new CacheId(new Object[] { new WeakObjectWrapper(object) });
        }
        CacheKey cacheKey = session.getIdentityMapAccessorInstance().getCacheKeyForObject(pk, getDescriptor().getJavaClass(), getDescriptor(), false);
        if ((cacheKey != null) && (cacheKey.getRecord() != null)) {
            XMLRecord nestedRecord = (XMLRecord) cacheKey.getRecord();
            nestedRecord.setMarshaller(parentRecord.getMarshaller());
            nestedRecord.setLeafElementType(parentRecord.getLeafElementType());
            parentRecord.setLeafElementType((XPathQName) null);
            return buildIntoNestedRow(nestedRecord, object, session);
        }
    }
    Element newNode = XPathEngine.getInstance().createUnownedElement(parentRecord.getDOM(), (Field) xmlField);
    XMLRecord nestedRecord = new DOMRecord(newNode);
    nestedRecord.setNamespaceResolver(parentRecord.getNamespaceResolver());
    nestedRecord.setMarshaller(parentRecord.getMarshaller());
    nestedRecord.setLeafElementType(parentRecord.getLeafElementType());
    parentRecord.setLeafElementType((XPathQName) null);
    return buildIntoNestedRow(nestedRecord, object, session);
}
Also used : CacheId(org.eclipse.persistence.internal.identitymaps.CacheId) DOMRecord(org.eclipse.persistence.oxm.record.DOMRecord) Element(org.w3c.dom.Element) XMLRecord(org.eclipse.persistence.oxm.record.XMLRecord) CacheKey(org.eclipse.persistence.internal.identitymaps.CacheKey)

Example 9 with CacheId

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

the class ReferenceResolver method getValue.

/**
 * Add java doc if you understand this code.
 */
private Object getValue(final CoreAbstractSession session, final Reference reference, final CacheId primaryKey, final ErrorHandler handler) {
    final Class<?> referenceTargetClass = reference.getTargetClass();
    if (null == referenceTargetClass || referenceTargetClass == CoreClassConstants.OBJECT) {
        for (Object entry : session.getDescriptors().values()) {
            Object value = null;
            final Descriptor targetDescriptor = (Descriptor) entry;
            final List pkFields = targetDescriptor.getPrimaryKeyFields();
            if (null != pkFields && 1 == pkFields.size()) {
                Field pkField = (Field) pkFields.get(0);
                pkField = (Field) targetDescriptor.getTypedField(pkField);
                final Class<?> targetType = pkField.getType();
                if (targetType == CoreClassConstants.STRING || targetType == CoreClassConstants.OBJECT) {
                    value = getValue(targetDescriptor.getJavaClass(), primaryKey);
                } else {
                    try {
                        final Object[] pkValues = primaryKey.getPrimaryKey();
                        final Object[] convertedPkValues = new Object[pkValues.length];
                        for (int x = 0; x < pkValues.length; x++) {
                            convertedPkValues[x] = session.getDatasourcePlatform().getConversionManager().convertObject(pkValues[x], targetType);
                        }
                        value = getValue(targetDescriptor.getJavaClass(), new CacheId(convertedPkValues));
                    } catch (ConversionException ignored) {
                    }
                }
                if (null != value) {
                    return value;
                }
            }
        }
        if (primaryKey.getPrimaryKey()[0] != null) {
            final XMLMarshalException e = XMLMarshalException.missingIDForIDRef(Object.class.getName(), primaryKey.getPrimaryKey());
            if (handler != null) {
                final SAXParseException saxParseException = new SAXParseException(e.getLocalizedMessage(), null, e);
                try {
                    handler.warning(saxParseException);
                } catch (SAXException saxException) {
                    throw e;
                }
            }
        }
        return null;
    } else {
        Object value = getValue(referenceTargetClass, primaryKey);
        if (null == value) {
            final CoreMapping mapping = (CoreMapping) reference.getMapping();
            final CoreDescriptor targetDescriptor = mapping.getReferenceDescriptor();
            if (targetDescriptor.hasInheritance()) {
                final CoreInheritancePolicy inheritancePolicy = targetDescriptor.getInheritancePolicy();
                final List<CoreDescriptor> childDescriptors = inheritancePolicy.getAllChildDescriptors();
                for (CoreDescriptor childDescriptor : childDescriptors) {
                    value = getValue(childDescriptor.getJavaClass(), primaryKey);
                    if (null != value) {
                        return value;
                    }
                }
            }
        }
        if (value == null && (primaryKey.getPrimaryKey()[0] != null)) {
            final XMLMarshalException e = XMLMarshalException.missingIDForIDRef(referenceTargetClass.getName(), primaryKey.getPrimaryKey());
            if (handler != null) {
                SAXParseException saxParseException = new SAXParseException(e.getLocalizedMessage(), null, e);
                try {
                    handler.warning(saxParseException);
                } catch (SAXException saxException) {
                    throw e;
                }
            }
        }
        return value;
    }
}
Also used : ConversionException(org.eclipse.persistence.exceptions.ConversionException) CoreDescriptor(org.eclipse.persistence.core.descriptors.CoreDescriptor) CoreMapping(org.eclipse.persistence.core.mappings.CoreMapping) CoreInheritancePolicy(org.eclipse.persistence.core.descriptors.CoreInheritancePolicy) SAXException(org.xml.sax.SAXException) Field(org.eclipse.persistence.internal.oxm.mappings.Field) CacheId(org.eclipse.persistence.internal.identitymaps.CacheId) SAXParseException(org.xml.sax.SAXParseException) Descriptor(org.eclipse.persistence.internal.oxm.mappings.Descriptor) CoreDescriptor(org.eclipse.persistence.core.descriptors.CoreDescriptor) ArrayList(java.util.ArrayList) List(java.util.List) XMLMarshalException(org.eclipse.persistence.exceptions.XMLMarshalException)

Example 10 with CacheId

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

the class ReferenceResolver method perform.

/**
 * Add java doc if you understand this code.
 */
private void perform(final CoreAbstractSession session, final IDResolver userSpecifiedResolver, final ErrorHandler handler, final Reference reference) {
    final Object referenceSourceObject = reference.getSourceObject();
    if (reference.getMapping() instanceof CollectionReferenceMapping) {
        final CollectionReferenceMapping mapping = (CollectionReferenceMapping) reference.getMapping();
        final CoreContainerPolicy cPolicy = mapping.getContainerPolicy();
        // container should never be null
        final Object container = reference.getContainer();
        // create vectors of primary key values - one vector per reference instance
        createPKVectorsFromMap(reference, mapping);
        // if the we could not generate the primary key for the reference, it will not resolve - skip it
        if (reference.getPrimaryKey() == null) {
            return;
        }
        // loop over each pk vector and get object from cache - then add to collection and set on object
        Object value = null;
        if (!mapping.isWriteOnly()) {
            for (Object o : ((Vector) reference.getPrimaryKey())) {
                final CacheId primaryKey = (CacheId) o;
                if (userSpecifiedResolver != null) {
                    final Callable c;
                    try {
                        if (primaryKey.getPrimaryKey().length > 1) {
                            final Map<String, Object> idWrapper = new HashMap<>();
                            for (int y = 0; y < primaryKey.getPrimaryKey().length; y++) {
                                final ObjectReferenceMapping refMapping = (ObjectReferenceMapping) reference.getMapping();
                                final String idName = (String) refMapping.getReferenceDescriptor().getPrimaryKeyFieldNames().get(y);
                                final Object idValue = primaryKey.getPrimaryKey()[y];
                                idWrapper.put(idName, idValue);
                            }
                            c = userSpecifiedResolver.resolve(idWrapper, reference.getTargetClass());
                        } else {
                            c = userSpecifiedResolver.resolve(primaryKey.getPrimaryKey()[0], reference.getTargetClass());
                        }
                        if (c != null) {
                            value = c.call();
                        }
                    } catch (Exception e) {
                        throw XMLMarshalException.unmarshalException(e);
                    }
                } else {
                    value = getValue(session, reference, primaryKey, handler);
                }
                if (value != null) {
                    cPolicy.addInto(value, container, session);
                }
            }
        }
        // for each reference, get the source object and add it to the container policy
        // when finished, set the policy on the mapping
        mapping.setAttributeValueInObject(referenceSourceObject, container);
        final InverseReferenceMapping inverseReferenceMapping = mapping.getInverseReferenceMapping();
        if (inverseReferenceMapping != null && value != null) {
            final CoreAttributeAccessor backpointerAccessor = inverseReferenceMapping.getAttributeAccessor();
            final CoreContainerPolicy backpointerContainerPolicy = inverseReferenceMapping.getContainerPolicy();
            if (backpointerContainerPolicy == null) {
                backpointerAccessor.setAttributeValueInObject(value, referenceSourceObject);
            } else {
                Object backpointerContainer = backpointerAccessor.getAttributeValueFromObject(value);
                if (backpointerContainer == null) {
                    backpointerContainer = backpointerContainerPolicy.containerInstance();
                    backpointerAccessor.setAttributeValueInObject(value, backpointerContainer);
                }
                backpointerContainerPolicy.addInto(referenceSourceObject, backpointerContainer, session);
            }
        }
    } else if (reference.getMapping() instanceof ObjectReferenceMapping) {
        final CacheId primaryKey = (CacheId) reference.getPrimaryKey();
        Object value = null;
        if (userSpecifiedResolver != null) {
            final Callable c;
            try {
                if (primaryKey.getPrimaryKey().length > 1) {
                    final Map<String, Object> idWrapper = new HashMap<>();
                    for (int y = 0; y < primaryKey.getPrimaryKey().length; y++) {
                        final ObjectReferenceMapping refMapping = (ObjectReferenceMapping) reference.getMapping();
                        final String idName = (String) refMapping.getReferenceDescriptor().getPrimaryKeyFieldNames().get(y);
                        final Object idValue = primaryKey.getPrimaryKey()[y];
                        idWrapper.put(idName, idValue);
                    }
                    c = userSpecifiedResolver.resolve(idWrapper, reference.getTargetClass());
                } else {
                    c = userSpecifiedResolver.resolve(primaryKey.getPrimaryKey()[0], reference.getTargetClass());
                }
                if (c != null) {
                    value = c.call();
                }
            } catch (Exception e) {
                throw XMLMarshalException.unmarshalException(e);
            }
        } else {
            value = getValue(session, reference, primaryKey, handler);
        }
        ObjectReferenceMapping mapping = (ObjectReferenceMapping) reference.getMapping();
        if (value != null) {
            mapping.setAttributeValueInObject(reference.getSourceObject(), value);
        }
        if (null != reference.getSetting()) {
            reference.getSetting().setValue(value);
        }
        InverseReferenceMapping inverseReferenceMapping = mapping.getInverseReferenceMapping();
        if (inverseReferenceMapping != null) {
            CoreAttributeAccessor backpointerAccessor = inverseReferenceMapping.getAttributeAccessor();
            CoreContainerPolicy backpointerContainerPolicy = inverseReferenceMapping.getContainerPolicy();
            if (backpointerContainerPolicy == null) {
                backpointerAccessor.setAttributeValueInObject(value, referenceSourceObject);
            } else {
                Object backpointerContainer = backpointerAccessor.getAttributeValueFromObject(value);
                if (backpointerContainer == null) {
                    backpointerContainer = backpointerContainerPolicy.containerInstance();
                    backpointerAccessor.setAttributeValueInObject(value, backpointerContainer);
                }
                backpointerContainerPolicy.addInto(reference.getSourceObject(), backpointerContainer, session);
            }
        }
    }
}
Also used : InverseReferenceMapping(org.eclipse.persistence.internal.oxm.mappings.InverseReferenceMapping) ObjectReferenceMapping(org.eclipse.persistence.internal.oxm.mappings.ObjectReferenceMapping) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) CoreAttributeAccessor(org.eclipse.persistence.core.mappings.CoreAttributeAccessor) Callable(java.util.concurrent.Callable) XMLMarshalException(org.eclipse.persistence.exceptions.XMLMarshalException) SAXParseException(org.xml.sax.SAXParseException) SAXException(org.xml.sax.SAXException) ConversionException(org.eclipse.persistence.exceptions.ConversionException) CollectionReferenceMapping(org.eclipse.persistence.internal.oxm.mappings.CollectionReferenceMapping) CacheId(org.eclipse.persistence.internal.identitymaps.CacheId) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) CoreContainerPolicy(org.eclipse.persistence.internal.core.queries.CoreContainerPolicy)

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