Search in sources :

Example 1 with BatchFetchType

use of org.eclipse.persistence.annotations.BatchFetchType 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;
}
Also used : BatchFetchType(org.eclipse.persistence.annotations.BatchFetchType) ClassDescriptor(org.eclipse.persistence.descriptors.ClassDescriptor) ObjectExpression(org.eclipse.persistence.internal.expressions.ObjectExpression) Expression(org.eclipse.persistence.expressions.Expression) ReportQuery(org.eclipse.persistence.queries.ReportQuery) ReadAllQuery(org.eclipse.persistence.queries.ReadAllQuery) FetchGroup(org.eclipse.persistence.queries.FetchGroup) ExpressionBuilder(org.eclipse.persistence.expressions.ExpressionBuilder) ObjectLevelReadQuery(org.eclipse.persistence.queries.ObjectLevelReadQuery) ReadQuery(org.eclipse.persistence.queries.ReadQuery) ObjectExpression(org.eclipse.persistence.internal.expressions.ObjectExpression)

Example 2 with BatchFetchType

use of org.eclipse.persistence.annotations.BatchFetchType in project eclipselink by eclipse-ee4j.

the class DirectCollectionMapping method prepareNestedBatchQuery.

/**
 * INTERNAL:
 * Clone and prepare the selection query as a nested batch read query.
 * This is used for nested batch reading.
 */
@Override
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;
    }
    DataReadQuery batchQuery = new DataReadQuery();
    batchQuery.setName(getAttributeName());
    // Join the query where clause with the mappings,
    // this will cause a join that should bring in all of the target objects.
    ExpressionBuilder builder;
    Expression originalSelectionCriteria = null;
    // 2612538 - the default size of Map (32) is appropriate
    Map<Expression, Expression> clonedExpressions = new IdentityHashMap<>();
    builder = new ExpressionBuilder();
    // For flashback.
    if (query.hasAsOfClause()) {
        builder.asOf(query.getAsOfClause());
    }
    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);
        }
        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 {
        // otherwise the original query will be corrupted.
        if (query.getSelectionCriteria() != null) {
            originalSelectionCriteria = query.getSelectionCriteria().copiedVersionFrom(clonedExpressions);
            builder = originalSelectionCriteria.getBuilder();
        }
        // Using a join, (WHERE <orginal-query-criteria> AND <mapping-join>)
        if (this.selectionQuery.isReadAllQuery()) {
            batchSelectionCriteria = builder.twist(this.selectionQuery.getSelectionCriteria(), builder);
        } else {
            batchSelectionCriteria = builder.twist(this.selectionQuery.getSQLStatement().getWhereClause(), builder);
        }
        // For 2729729, rebuildOn is not needed as the base is still the same.
        if (originalSelectionCriteria != null) {
            batchSelectionCriteria = batchSelectionCriteria.and(originalSelectionCriteria);
        }
        if (descriptorToUse.getQueryManager().getAdditionalJoinExpression() != null) {
            batchSelectionCriteria = batchSelectionCriteria.and(query.getDescriptor().getQueryManager().getAdditionalJoinExpression().rebuildOn(builder));
        }
        if (this.historyPolicy != null) {
            if (query.getSession().getAsOfClause() != null) {
                builder.asOf(query.getSession().getAsOfClause());
            } else if (builder.getAsOfClause() == null) {
                builder.asOf(AsOfClause.NO_CLAUSE);
            }
            batchSelectionCriteria = batchSelectionCriteria.and(this.historyPolicy.additionalHistoryExpression(builder, builder));
        }
    }
    SQLSelectStatement batchStatement = new SQLSelectStatement();
    for (DatabaseField keyField : getReferenceKeyFields()) {
        batchStatement.addField(builder.getTable(this.referenceTable).getField(keyField));
    }
    batchStatement.addField(builder.getTable(this.referenceTable).getField(this.directField));
    batchStatement.setWhereClause(batchSelectionCriteria);
    batchQuery.setSQLStatement(batchStatement);
    this.containerPolicy.addAdditionalFieldsToQuery(batchQuery, getAdditionalFieldsBaseExpression(batchQuery));
    batchStatement.normalize(query.getSession(), descriptorToUse, clonedExpressions);
    return batchQuery;
}
Also used : BatchFetchType(org.eclipse.persistence.annotations.BatchFetchType) ClassDescriptor(org.eclipse.persistence.descriptors.ClassDescriptor) ObjectExpression(org.eclipse.persistence.internal.expressions.ObjectExpression) Expression(org.eclipse.persistence.expressions.Expression) TableExpression(org.eclipse.persistence.internal.expressions.TableExpression) ReportQuery(org.eclipse.persistence.queries.ReportQuery) IdentityHashMap(java.util.IdentityHashMap) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField) DataReadQuery(org.eclipse.persistence.queries.DataReadQuery) SQLSelectStatement(org.eclipse.persistence.internal.expressions.SQLSelectStatement) ExpressionBuilder(org.eclipse.persistence.expressions.ExpressionBuilder)

Aggregations

BatchFetchType (org.eclipse.persistence.annotations.BatchFetchType)2 ClassDescriptor (org.eclipse.persistence.descriptors.ClassDescriptor)2 Expression (org.eclipse.persistence.expressions.Expression)2 ExpressionBuilder (org.eclipse.persistence.expressions.ExpressionBuilder)2 ObjectExpression (org.eclipse.persistence.internal.expressions.ObjectExpression)2 ReportQuery (org.eclipse.persistence.queries.ReportQuery)2 IdentityHashMap (java.util.IdentityHashMap)1 SQLSelectStatement (org.eclipse.persistence.internal.expressions.SQLSelectStatement)1 TableExpression (org.eclipse.persistence.internal.expressions.TableExpression)1 DatabaseField (org.eclipse.persistence.internal.helper.DatabaseField)1 DataReadQuery (org.eclipse.persistence.queries.DataReadQuery)1 FetchGroup (org.eclipse.persistence.queries.FetchGroup)1 ObjectLevelReadQuery (org.eclipse.persistence.queries.ObjectLevelReadQuery)1 ReadAllQuery (org.eclipse.persistence.queries.ReadAllQuery)1 ReadQuery (org.eclipse.persistence.queries.ReadQuery)1