use of org.eclipse.persistence.internal.expressions.ObjectExpression in project eclipselink by eclipse-ee4j.
the class ObjectBuilder method loadJoinedAttributes.
protected void loadJoinedAttributes(ClassDescriptor concreteDescriptor, Object sourceObject, CacheKey cacheKey, AbstractRecord databaseRow, JoinedAttributeManager joinManager, ObjectBuildingQuery query, boolean isTargetProtected) {
boolean useOnlyMappingsExcludedFromSOP = false;
if (concreteDescriptor.hasSerializedObjectPolicy() && query.shouldUseSerializedObjectPolicy()) {
// sopObject has not been deserialized, sourceObject must be cached
useOnlyMappingsExcludedFromSOP = databaseRow.get(concreteDescriptor.getSerializedObjectPolicy().getField()) != null;
}
Boolean isUntriggeredResultSetRecord = null;
List<Expression> joinExpressions = joinManager.getJoinedAttributeExpressions();
int size = joinExpressions.size();
for (int index = 0; index < size; index++) {
QueryKeyExpression queryKeyExpression = (QueryKeyExpression) joinExpressions.get(index);
QueryKeyExpression baseExpression = (QueryKeyExpression) joinManager.getJoinedAttributes().get(index);
DatabaseMapping mapping = joinManager.getJoinedAttributeMappings().get(index);
// Only worry about immediate (excluding aggregates) foreign reference mapping attributes.
if (queryKeyExpression == baseExpression) {
if (mapping == null) {
throw ValidationException.missingMappingForAttribute(concreteDescriptor, queryKeyExpression.getName(), toString());
} else {
if (!useOnlyMappingsExcludedFromSOP || mapping.isOutSopObject()) {
// get the intermediate objects between this expression node and the base builder
Object intermediateValue = joinManager.getValueFromObjectForExpression(query.getExecutionSession(), sourceObject, (ObjectExpression) baseExpression.getBaseExpression());
// Bug 4230655 - do not replace instantiated valueholders.
Object attributeValue = mapping.getAttributeValueFromObject(intermediateValue);
if ((attributeValue != null) && mapping.isForeignReferenceMapping() && ((ForeignReferenceMapping) mapping).usesIndirection() && (!((ForeignReferenceMapping) mapping).getIndirectionPolicy().objectIsInstantiated(attributeValue))) {
if (mapping.isObjectReferenceMapping() && ((ObjectReferenceMapping) mapping).isForeignKeyRelationship() && !mapping.isPrimaryKeyMapping()) {
if (isUntriggeredResultSetRecord == null) {
isUntriggeredResultSetRecord = databaseRow instanceof ResultSetRecord && ((ResultSetRecord) databaseRow).hasResultSet();
}
if (isUntriggeredResultSetRecord) {
for (DatabaseField field : mapping.getFields()) {
// extract the values from ResultSet into the row
databaseRow.get(field);
}
}
}
AbstractSession session = query.getExecutionSession();
mapping.readFromRowIntoObject(databaseRow, joinManager, intermediateValue, cacheKey, query, query.getExecutionSession(), isTargetProtected);
session.getIdentityMapAccessorInstance().getIdentityMap(concreteDescriptor).lazyRelationshipLoaded(intermediateValue, (ValueHolderInterface) ((ForeignReferenceMapping) mapping).getIndirectionPolicy().getOriginalValueHolder(attributeValue, session), (ForeignReferenceMapping) mapping);
}
}
}
}
}
}
use of org.eclipse.persistence.internal.expressions.ObjectExpression in project eclipselink by eclipse-ee4j.
the class ForeignReferenceMapping method prepareNestedBatchQuery.
/**
* INTERNAL:
* Clone and prepare the selection query as a nested batch read query.
* This is used for nested batch reading.
*/
public ReadQuery prepareNestedBatchQuery(ObjectLevelReadQuery query) {
// For CR#2646-S.M. In case of inheritance the descriptor to use may not be that
// of the source query (the base class descriptor), but that of the subclass, if the
// attribute is only of the subclass. Thus in this case use the descriptor from the mapping.
// Also: for Bug 5478648 - Do not switch the descriptor if the query's descriptor is an aggregate
ClassDescriptor descriptorToUse = query.getDescriptor();
if ((descriptorToUse != this.descriptor) && (!descriptorToUse.getMappings().contains(this)) && (!this.descriptor.isDescriptorTypeAggregate())) {
descriptorToUse = this.descriptor;
}
ExpressionBuilder builder = new ExpressionBuilder(this.referenceClass);
builder.setQueryClassAndDescriptor(this.referenceClass, getReferenceDescriptor());
ReadAllQuery batchQuery = new ReadAllQuery(this.referenceClass, builder);
batchQuery.setName(getAttributeName());
batchQuery.setDescriptor(getReferenceDescriptor());
batchQuery.setSession(query.getSession());
batchQuery.setShouldUseSerializedObjectPolicy(query.shouldUseSerializedObjectPolicy());
// bug 3965568
// we should not wrap the results as this is an internal query
batchQuery.setShouldUseWrapperPolicy(false);
if (query.shouldCascadeAllParts() || (query.shouldCascadePrivateParts() && isPrivateOwned()) || (query.shouldCascadeByMapping() && this.cascadeRefresh)) {
batchQuery.setShouldRefreshIdentityMapResult(query.shouldRefreshIdentityMapResult());
batchQuery.setCascadePolicy(query.getCascadePolicy());
batchQuery.setShouldMaintainCache(query.shouldMaintainCache());
if (query.hasAsOfClause()) {
batchQuery.setAsOfClause(query.getAsOfClause());
}
// bug 3802197 - cascade binding and prepare settings
batchQuery.setShouldBindAllParameters(query.getShouldBindAllParameters());
batchQuery.setShouldPrepare(query.shouldPrepare());
}
batchQuery.setShouldOuterJoinSubclasses(query.shouldOuterJoinSubclasses());
// CR #4365
batchQuery.setQueryId(query.getQueryId());
Expression batchSelectionCriteria = null;
// Build the batch query, either using joining, or an exist sub-select.
BatchFetchType batchType = query.getBatchFetchPolicy().getType();
if (this.batchFetchType != null) {
batchType = this.batchFetchType;
}
if (batchType == BatchFetchType.EXISTS) {
// Using a EXISTS sub-select (WHERE EXIST (<original-query> AND <mapping-join> AND <mapping-join>)
ExpressionBuilder subBuilder = new ExpressionBuilder(descriptorToUse.getJavaClass());
subBuilder.setQueryClassAndDescriptor(descriptorToUse.getJavaClass(), descriptorToUse);
ReportQuery subQuery = new ReportQuery(descriptorToUse.getJavaClass(), subBuilder);
subQuery.setDescriptor(descriptorToUse);
subQuery.setShouldRetrieveFirstPrimaryKey(true);
Expression subCriteria = subBuilder.twist(getSelectionCriteria(), builder);
if (query.getSelectionCriteria() != null) {
// For bug 2612567, any query can have batch attributes, so the
// original selection criteria can be quite complex, with multiple
// builders (i.e. for parallel selects).
// Now uses cloneUsing(newBase) instead of rebuildOn(newBase).
subCriteria = query.getSelectionCriteria().cloneUsing(subBuilder).and(subCriteria);
}
// Check for history and set asOf.
if (descriptorToUse.getHistoryPolicy() != null) {
if (query.getSession().getAsOfClause() != null) {
subBuilder.asOf(query.getSession().getAsOfClause());
} else if (batchQuery.getAsOfClause() == null) {
subBuilder.asOf(AsOfClause.NO_CLAUSE);
} else {
subBuilder.asOf(batchQuery.getAsOfClause());
}
}
subQuery.setSelectionCriteria(subCriteria);
batchSelectionCriteria = builder.exists(subQuery);
} else if (batchType == BatchFetchType.IN) {
// Using a IN with foreign key values (WHERE FK IN :QUERY_BATCH_PARAMETER)
batchSelectionCriteria = buildBatchCriteria(builder, query);
} else {
// Using a join, (WHERE <orginal-query-criteria> AND <mapping-join>)
// Join the query where clause with the mapping's,
// this will cause a join that should bring in all of the target objects.
Expression backRef = builder.getManualQueryKey(getAttributeName() + "-back-ref", descriptorToUse);
batchSelectionCriteria = backRef.twist(getSelectionCriteria(), builder);
if (query.getSelectionCriteria() != null) {
// For bug 2612567, any query can have batch attributes, so the
// original selection criteria can be quite complex, with multiple
// builders (i.e. for parallel selects).
// Now uses cloneUsing(newBase) instead of rebuildOn(newBase).
batchSelectionCriteria = batchSelectionCriteria.and(query.getSelectionCriteria().cloneUsing(backRef));
}
// to somehow keep all this code inside QueryKeyExpression.normalize.
if (descriptorToUse.getQueryManager().getAdditionalJoinExpression() != null) {
batchSelectionCriteria = batchSelectionCriteria.and(descriptorToUse.getQueryManager().getAdditionalJoinExpression().rebuildOn(backRef));
}
// Check for history and add history expression.
if (descriptorToUse.getHistoryPolicy() != null) {
if (query.getSession().getAsOfClause() != null) {
backRef.asOf(query.getSession().getAsOfClause());
} else if (batchQuery.getAsOfClause() == null) {
backRef.asOf(AsOfClause.NO_CLAUSE);
} else {
backRef.asOf(batchQuery.getAsOfClause());
}
batchSelectionCriteria = batchSelectionCriteria.and(descriptorToUse.getHistoryPolicy().additionalHistoryExpression(backRef, backRef));
}
}
batchQuery.setSelectionCriteria(batchSelectionCriteria);
if (query.isDistinctComputed()) {
// Only recompute if it has not already been set by the user
batchQuery.setDistinctState(query.getDistinctState());
}
// Add batch reading attributes contained in the mapping's query.
ReadQuery mappingQuery = this.selectionQuery;
if (mappingQuery.isReadAllQuery()) {
// CR#3238 clone these vectors so they will not grow with each call to the query. -TW
batchQuery.setOrderByExpressions(new ArrayList<>(((ReadAllQuery) mappingQuery).getOrderByExpressions()));
if (((ReadAllQuery) mappingQuery).hasBatchReadAttributes()) {
for (Expression expression : ((ReadAllQuery) mappingQuery).getBatchReadAttributeExpressions()) {
batchQuery.addBatchReadAttribute(expression);
}
}
}
// has been using inheritance and child descriptors can have different mappings.
if (query.hasBatchReadAttributes()) {
for (Expression expression : query.getBatchReadAttributeExpressions()) {
ObjectExpression batchReadExpression = (ObjectExpression) expression;
// Batch Read Attribute Expressions may not have initialized.
ExpressionBuilder expressionBuilder = batchReadExpression.getBuilder();
if (expressionBuilder.getQueryClass() == null) {
expressionBuilder.setQueryClass(query.getReferenceClass());
}
if (expressionBuilder.getSession() == null) {
expressionBuilder.setSession(query.getSession().getRootSession(null));
}
}
// Computed nested batch attribute expressions, and add them to batch query.
List<Expression> nestedExpressions = extractNestedExpressions(query.getBatchReadAttributeExpressions(), batchQuery.getExpressionBuilder());
batchQuery.getBatchReadAttributeExpressions().addAll(nestedExpressions);
}
batchQuery.setBatchFetchType(batchType);
batchQuery.setBatchFetchSize(query.getBatchFetchPolicy().getSize());
// Allow subclasses to further prepare.
postPrepareNestedBatchQuery(batchQuery, query);
// Set nested fetch group.
if (batchQuery.getDescriptor().hasFetchGroupManager()) {
FetchGroup sourceFetchGroup = query.getExecutionFetchGroup();
if (sourceFetchGroup != null) {
FetchGroup targetFetchGroup = sourceFetchGroup.getGroup(getAttributeName());
if (targetFetchGroup != null) {
batchQuery.setFetchGroup(targetFetchGroup);
}
}
}
if (batchQuery.shouldPrepare()) {
batchQuery.checkPrepare(query.getSession(), query.getTranslationRow());
}
batchQuery.setSession(null);
return batchQuery;
}
use of org.eclipse.persistence.internal.expressions.ObjectExpression in project eclipselink by eclipse-ee4j.
the class DirectCollectionMapping method getJoinCriteria.
/**
* INTERNAL:
* Returns the join criteria stored in the mapping selection query. This criteria
* is used to read reference objects across the tables from the database.
*/
@Override
public Expression getJoinCriteria(ObjectExpression context, Expression base) {
if (getHistoryPolicy() != null) {
Expression result = super.getJoinCriteria(context, base);
Expression historyCriteria = getHistoryPolicy().additionalHistoryExpression(context, base);
if (result != null) {
return result.and(historyCriteria);
} else if (historyCriteria != null) {
return historyCriteria;
} else {
return null;
}
} else {
return super.getJoinCriteria(context, base);
}
}
use of org.eclipse.persistence.internal.expressions.ObjectExpression in project eclipselink by eclipse-ee4j.
the class DatabaseMapping method extractNestedNonAggregateExpressions.
/**
* INTERNAL:
* Extract the nested attribute expressions that apply to this mapping.
* This is used for joining, and locking.
* For aggregates return the nested foreign reference mapping, not the aggregate, as the aggregates are not joined,
* and share their parent's query.
*
* @param expressions TODO
* @param newRoot TODO
* @param rootExpressionsAllowed true if newRoot itself can be one of the
* expressions returned (used for locking)
* @return TODO
*/
protected List<Expression> extractNestedNonAggregateExpressions(List<Expression> expressions, ExpressionBuilder newRoot, boolean rootExpressionsAllowed) {
List<Expression> nestedExpressions = new ArrayList<>(expressions.size());
/*
* need to work on all expressions with at least 2 nestings off the base expression builder, excluding
* aggregateObjectMapping expressions from the count (only ForeignReferenceMapping expressions count). For those
* expressions, If the expression closest to to the Builder is for this mapping, that expression is rebuilt using
* newRoot and added to the nestedExpressions list.
*/
for (Expression next : expressions) {
// the ForUpdateOfClause.
if (!next.isQueryKeyExpression()) {
continue;
}
QueryKeyExpression expression = (QueryKeyExpression) next;
ObjectExpression base = expression;
boolean afterBase = false;
boolean done = false;
ObjectExpression prevExpression = base;
while (!base.getBaseExpression().isExpressionBuilder() && !done) {
base = (ObjectExpression) base.getBaseExpression();
while (!base.isExpressionBuilder() && (base.getMapping() != null && base.getMapping().isAggregateObjectMapping())) {
base = (ObjectExpression) base.getBaseExpression();
}
if (base.isExpressionBuilder()) {
done = true;
// use the one closest to the expression builder that wasn't an aggregate
base = prevExpression;
} else {
prevExpression = base;
afterBase = true;
}
}
if (afterBase && base.getName().equals(getAttributeName())) {
nestedExpressions.add(expression.rebuildOn(base, newRoot));
} else if (rootExpressionsAllowed && expression.getBaseExpression().isExpressionBuilder() && expression.getName().equals(getAttributeName())) {
nestedExpressions.add(newRoot);
}
}
return nestedExpressions;
}
use of org.eclipse.persistence.internal.expressions.ObjectExpression in project eclipselink by eclipse-ee4j.
the class JoinedAttributeManager method addExpressionAndBaseToGroupedList.
/**
* adds expression and its base expressions recursively to the expressionList in groups, so that an expression is never listed before
* its base expression
*/
protected Expression addExpressionAndBaseToGroupedList(Expression expression, List expressionlist, Expression lastJoinedAttributeBaseExpression) {
if (!expressionlist.contains(expression)) {
int baseExpressionIndex = -1;
// better than using instanceof BaseExpression. If its not an objectExpression, it will get an exception in prepare anyway
boolean sameBase = false;
if ((expression.isObjectExpression())) {
Expression baseExpression = ((BaseExpression) expression).getBaseExpression();
// filter out aggregate expressions between this and the next node.
while (!baseExpression.isExpressionBuilder() && ((QueryKeyExpression) baseExpression).getMapping().isAggregateMapping()) {
baseExpression = ((BaseExpression) baseExpression).getBaseExpression();
}
if (baseExpression != null && !baseExpression.isExpressionBuilder()) {
addExpressionAndBaseToGroupedList(baseExpression, expressionlist, lastJoinedAttributeBaseExpression);
// EL bug 307497
if (baseExpression != lastJoinedAttributeBaseExpression) {
baseExpressionIndex = getJoinedAttributeExpressions().indexOf(baseExpression);
} else {
sameBase = true;
}
}
}
// EL bug 307497
if (baseExpressionIndex == -1) {
expressionlist.add(expression);
if (!sameBase) {
lastJoinedAttributeBaseExpression = expression;
}
} else {
// Add attributeExpression at baseExpressionIndex + 1.
expressionlist.add(baseExpressionIndex + 1, expression);
}
}
return lastJoinedAttributeBaseExpression;
}
Aggregations