use of org.eclipse.persistence.internal.queries.ContainerPolicy in project eclipselink by eclipse-ee4j.
the class ObjectBuildingQuery method triggerJoinExpressions.
/**
* INTERNAL:
* Fetch/trigger indirection on the clone passed in, based on join expressions in the joinManager.
*/
private void triggerJoinExpressions(UnitOfWorkImpl unitOfWork, JoinedAttributeManager joinManager, Object clone, ClassDescriptor concreteDescriptor) {
List<Expression> joinExpressions = joinManager.getJoinedAttributeExpressions();
int size = joinExpressions.size();
if ((size == 0) || (clone == null)) {
return;
}
for (int index = 0; index < size; index++) {
// since a's descriptor won't have a mapping for 'b'.
// baseExpression will be first relationship expression after the ExpressionBuilder, and may include aggregate intermediaries
QueryKeyExpression baseExpression = (QueryKeyExpression) joinManager.getJoinedAttributes().get(index);
DatabaseMapping mapping = joinManager.getJoinedAttributeMappings().get(index);
if (mapping != null) {
Object attributeValue = joinManager.getValueFromObjectForExpression(unitOfWork, clone, baseExpression);
if (attributeValue != null) {
// recurse through the mapping if the expression's base isn't the base expressionBuilder
QueryKeyExpression queryKeyExpression = (QueryKeyExpression) joinExpressions.get(index);
if (baseExpression != queryKeyExpression) {
ObjectLevelReadQuery nestedQuery = null;
if (joinManager.getJoinedMappingQueryClones() == null) {
if (joinManager.getJoinedMappingQueries_() != null) {
nestedQuery = joinManager.getJoinedMappingQueries_().get(mapping);
}
} else {
nestedQuery = joinManager.getJoinedMappingQueryClones().get(mapping);
}
// use the nestedQuery to trigger joins remaining for this expression (base onward)
if ((nestedQuery != null) && (nestedQuery.getJoinedAttributeManager() != null)) {
if (!mapping.isCollectionMapping()) {
triggerJoinExpressions(unitOfWork, nestedQuery.getJoinedAttributeManager(), attributeValue, null);
} else {
ContainerPolicy cp = mapping.getContainerPolicy();
Object iterator = cp.iteratorFor(attributeValue);
while (cp.hasNext(iterator)) {
triggerJoinExpressions(unitOfWork, nestedQuery.getJoinedAttributeManager(), cp.next(iterator, unitOfWork), null);
}
}
}
}
}
}
}
}
use of org.eclipse.persistence.internal.queries.ContainerPolicy in project eclipselink by eclipse-ee4j.
the class ObjectBuilder method buildObjectsInto.
/**
* Return a container which contains the instances of the receivers javaClass.
* Set the fields of the instance to the values stored in the database rows.
*/
public Object buildObjectsInto(ReadAllQuery query, List databaseRows, Object domainObjects) {
if (databaseRows instanceof ThreadCursoredList) {
return buildObjectsFromCursorInto(query, databaseRows, domainObjects);
}
int size = databaseRows.size();
if (size > 0) {
AbstractSession session = query.getSession();
session.startOperationProfile(SessionProfiler.ObjectBuilding, query, SessionProfiler.ALL);
try {
InheritancePolicy inheritancePolicy = null;
if (this.descriptor.hasInheritance()) {
inheritancePolicy = this.descriptor.getInheritancePolicy();
}
boolean isUnitOfWork = session.isUnitOfWork();
boolean shouldCacheQueryResults = query.shouldCacheQueryResults();
boolean shouldUseWrapperPolicy = query.shouldUseWrapperPolicy();
// PERF: Avoid lazy init of join manager if no joining.
JoinedAttributeManager joinManager = null;
if (query.hasJoining()) {
joinManager = query.getJoinedAttributeManager();
}
if (this.descriptor.getCachePolicy().shouldPrefetchCacheKeys() && query.shouldMaintainCache() && !query.shouldRetrieveBypassCache()) {
Object[] pkList = new Object[size];
for (int i = 0; i < size; ++i) {
pkList[i] = extractPrimaryKeyFromRow((AbstractRecord) databaseRows.get(i), session);
}
query.setPrefetchedCacheKeys(session.getIdentityMapAccessorInstance().getAllCacheKeysFromIdentityMapWithEntityPK(pkList, descriptor));
}
ContainerPolicy policy = query.getContainerPolicy();
if (policy.shouldAddAll()) {
List domainObjectsIn = new ArrayList(size);
List<AbstractRecord> databaseRowsIn = new ArrayList(size);
for (int index = 0; index < size; index++) {
AbstractRecord databaseRow = (AbstractRecord) databaseRows.get(index);
// PERF: 1-m joining nulls out duplicate rows.
if (databaseRow != null) {
domainObjectsIn.add(buildObject(query, databaseRow, joinManager, session, this.descriptor, inheritancePolicy, isUnitOfWork, shouldCacheQueryResults, shouldUseWrapperPolicy));
databaseRowsIn.add(databaseRow);
}
}
policy.addAll(domainObjectsIn, domainObjects, session, databaseRowsIn, query, null, true);
} else {
boolean quickAdd = (domainObjects instanceof Collection) && !this.hasWrapperPolicy;
for (int index = 0; index < size; index++) {
AbstractRecord databaseRow = (AbstractRecord) databaseRows.get(index);
// PERF: 1-m joining nulls out duplicate rows.
if (databaseRow != null) {
Object domainObject = buildObject(query, databaseRow, joinManager, session, this.descriptor, inheritancePolicy, isUnitOfWork, shouldCacheQueryResults, shouldUseWrapperPolicy);
if (quickAdd) {
((Collection) domainObjects).add(domainObject);
} else {
policy.addInto(domainObject, domainObjects, session, databaseRow, query, null, true);
}
}
}
}
} finally {
session.endOperationProfile(SessionProfiler.ObjectBuilding, query, SessionProfiler.ALL);
}
}
return domainObjects;
}
use of org.eclipse.persistence.internal.queries.ContainerPolicy in project eclipselink by eclipse-ee4j.
the class ObjectBuilder method buildObjectsFromResultSetInto.
/**
* Version of buildObjectsInto method that takes call instead of rows.
* Return a container which contains the instances of the receivers javaClass.
* Set the fields of the instance to the values stored in the result set.
*/
public Object buildObjectsFromResultSetInto(ReadAllQuery query, ResultSet resultSet, Vector fields, DatabaseField[] fieldsArray, Object domainObjects) throws SQLException {
AbstractSession session = query.getSession();
session.startOperationProfile(SessionProfiler.ObjectBuilding, query, SessionProfiler.ALL);
try {
boolean hasNext = resultSet.next();
if (hasNext) {
InheritancePolicy inheritancePolicy = null;
if (this.descriptor.hasInheritance()) {
inheritancePolicy = this.descriptor.getInheritancePolicy();
}
boolean isUnitOfWork = session.isUnitOfWork();
boolean shouldCacheQueryResults = query.shouldCacheQueryResults();
boolean shouldUseWrapperPolicy = query.shouldUseWrapperPolicy();
// PERF: Avoid lazy init of join manager if no joining.
JoinedAttributeManager joinManager = null;
if (query.hasJoining()) {
joinManager = query.getJoinedAttributeManager();
}
ContainerPolicy policy = query.getContainerPolicy();
// !cp.shouldAddAll() - query with SortedListContainerPolicy - currently does not use this method
boolean quickAdd = (domainObjects instanceof Collection) && !this.hasWrapperPolicy;
ResultSetMetaData metaData = resultSet.getMetaData();
ResultSetRecord row = null;
AbstractSession executionSession = query.getExecutionSession();
DatabaseAccessor dbAccessor = (DatabaseAccessor) query.getAccessor();
DatabasePlatform platform = dbAccessor.getPlatform();
boolean optimizeData = platform.shouldOptimizeDataConversion();
if (this.isSimple) {
// None of the fields are relational - the row could be reused, just clear all the values.
row = new SimpleResultSetRecord(fields, fieldsArray, resultSet, metaData, dbAccessor, executionSession, platform, optimizeData);
if (this.descriptor.isDescriptorTypeAggregate()) {
// Aggregate Collection may have an unmapped primary key referencing the owner, the corresponding field will not be used when the object is populated and therefore may not be cleared.
((SimpleResultSetRecord) row).setShouldKeepValues(true);
}
}
while (hasNext) {
if (!this.isSimple) {
row = new ResultSetRecord(fields, fieldsArray, resultSet, metaData, dbAccessor, executionSession, platform, optimizeData);
}
Object domainObject = buildObject(query, row, joinManager, session, this.descriptor, inheritancePolicy, isUnitOfWork, shouldCacheQueryResults, shouldUseWrapperPolicy);
if (quickAdd) {
((Collection) domainObjects).add(domainObject);
} else {
// query with MappedKeyMapPolicy currently does not use this method
policy.addInto(domainObject, domainObjects, session);
}
if (this.isSimple) {
((SimpleResultSetRecord) row).reset();
} else {
if (this.shouldKeepRow) {
if (row.hasResultSet()) {
// ResultSet has not been fully triggered - that means the cached object was used.
// Yet the row still may be cached in a value holder (see loadBatchReadAttributes and loadJoinedAttributes methods).
// Remove ResultSet to avoid attempt to trigger it (already closed) when pk or fk values (already extracted) accessed when the value holder is instantiated.
row.removeResultSet();
} else {
row.removeNonIndirectionValues();
}
}
}
hasNext = resultSet.next();
}
}
} finally {
session.endOperationProfile(SessionProfiler.ObjectBuilding, query, SessionProfiler.ALL);
}
return domainObjects;
}
use of org.eclipse.persistence.internal.queries.ContainerPolicy in project eclipselink by eclipse-ee4j.
the class TypeHelperImpl method resolveMapKey.
/**
* Returns the type of the map key for the mapping on ownerClass named attribute
* Returns null if that mapping does not exist or does not contain a map key
*/
@Override
public Object resolveMapKey(Object ownerClass, String attribute) {
Object type = null;
DatabaseMapping mapping = resolveAttributeMapping(ownerClass, attribute);
if (mapping.isCollectionMapping()) {
ContainerPolicy cp = mapping.getContainerPolicy();
type = cp.getKeyType();
}
return type;
}
use of org.eclipse.persistence.internal.queries.ContainerPolicy in project eclipselink by eclipse-ee4j.
the class DirectCollectionMapping method compareCollectionsForChange.
/**
* INTERNAL:
* This method is used to calculate the differences between two collections.
*/
@Override
public void compareCollectionsForChange(Object oldCollection, Object newCollection, ChangeRecord changeRecord, AbstractSession session) {
if (this.listOrderField != null) {
compareListsForChange((List) oldCollection, (List) newCollection, changeRecord, session);
return;
}
ContainerPolicy cp = getContainerPolicy();
int numberOfNewNulls = 0;
HashMap originalKeyValues = new HashMap(10);
HashMap cloneKeyValues = new HashMap(10);
if (oldCollection != null) {
Object backUpIter = cp.iteratorFor(oldCollection);
while (cp.hasNext(backUpIter)) {
// Make a lookup of the objects
Object secondObject = cp.next(backUpIter, session);
// For CR#2258/CR#2378 handle null values inserted in a collection.
if (secondObject == null) {
numberOfNewNulls--;
} else {
Integer count = (Integer) originalKeyValues.get(secondObject);
if (count == null) {
originalKeyValues.put(secondObject, 1);
} else {
originalKeyValues.put(secondObject, count + 1);
}
}
}
}
// should a removal occur this is the original count of objects on the database.
// this value is used to determine how many objects to re-insert after the delete as a
// delete will delete all of the objects not just one.
HashMap databaseCount = (HashMap) originalKeyValues.clone();
int databaseNullCount = Math.abs(numberOfNewNulls);
if (newCollection != null) {
Object cloneIter = cp.iteratorFor(newCollection);
/* The following code is used to compare objects in a direct collection.
Because objects in a direct collection are primitives and may be the same object
the following code must count the number of instances in the collection not just the
existence of an object.
*/
while (cp.hasNext(cloneIter)) {
// Compare them with the objects from the clone
Object firstObject = cp.next(cloneIter, session);
// For CR#2258/CR#2378 handle null values inserted in a collection.
if (firstObject == null) {
numberOfNewNulls++;
} else {
Integer count = (Integer) originalKeyValues.get(firstObject);
if (count == null) {
// the object was not in the backup
Integer cloneCount = (Integer) cloneKeyValues.get(firstObject);
// Add it to the additions hashtable
if (cloneCount == null) {
cloneKeyValues.put(firstObject, 1);
} else {
cloneKeyValues.put(firstObject, cloneCount + 1);
}
} else if (count == 1) {
// There is only one object so remove the whole reference
originalKeyValues.remove(firstObject);
} else {
originalKeyValues.put(firstObject, count - 1);
}
}
}
}
if (cloneKeyValues.isEmpty() && originalKeyValues.isEmpty() && (numberOfNewNulls == 0) && (!changeRecord.getOwner().isNew())) {
return;
}
((DirectCollectionChangeRecord) changeRecord).clearChanges();
((DirectCollectionChangeRecord) changeRecord).addAdditionChange(cloneKeyValues, databaseCount);
((DirectCollectionChangeRecord) changeRecord).addRemoveChange(originalKeyValues, databaseCount);
((DirectCollectionChangeRecord) changeRecord).setIsDeferred(false);
((DirectCollectionChangeRecord) changeRecord).setLatestCollection(null);
// For CR#2258, produce a changeRecord which reflects the addition and removal of null values.
if (numberOfNewNulls != 0) {
((DirectCollectionChangeRecord) changeRecord).getCommitAddMap().put(null, databaseNullCount);
if (numberOfNewNulls > 0) {
((DirectCollectionChangeRecord) changeRecord).addAdditionChange(null, numberOfNewNulls);
} else {
numberOfNewNulls *= -1;
((DirectCollectionChangeRecord) changeRecord).addRemoveChange(null, numberOfNewNulls);
}
}
}
Aggregations