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