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;
}
}
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;
}
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);
}
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;
}
}
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);
}
}
}
}
Aggregations