Search in sources :

Example 1 with BiDirectionalFetch

use of org.hibernate.sql.results.graph.BiDirectionalFetch in project hibernate-orm by hibernate.

the class LoaderSelectBuilder method createFetchableBiConsumer.

private BiConsumer<Fetchable, Boolean> createFetchableBiConsumer(FetchParent fetchParent, QuerySpec querySpec, LoaderSqlAstCreationState creationState, List<Fetch> fetches) {
    return (fetchable, isKeyFetchable) -> {
        final NavigablePath fetchablePath;
        if (isKeyFetchable) {
            final EntityIdentifierMapping identifierMapping;
            if (fetchParent instanceof BiDirectionalFetch) {
                final BiDirectionalFetch parentAsBiDirectionalFetch = (BiDirectionalFetch) fetchParent;
                final Fetchable biDirectionalFetchedMapping = parentAsBiDirectionalFetch.getFetchedMapping();
                if (biDirectionalFetchedMapping instanceof EntityValuedFetchable) {
                    identifierMapping = ((EntityValuedFetchable) biDirectionalFetchedMapping).getEntityMappingType().getIdentifierMapping();
                } else {
                    identifierMapping = null;
                }
            } else {
                final FetchableContainer fetchableContainer = fetchParent.getReferencedMappingContainer();
                if (fetchableContainer instanceof EntityValuedModelPart) {
                    final EntityValuedModelPart entityValuedModelPart = (EntityValuedModelPart) fetchableContainer;
                    identifierMapping = entityValuedModelPart.getEntityMappingType().getIdentifierMapping();
                } else {
                    identifierMapping = null;
                }
            }
            if (identifierMapping != null) {
                fetchablePath = new EntityIdentifierNavigablePath(fetchParent.getNavigablePath(), attributeName(identifierMapping));
            } else {
                fetchablePath = fetchParent.resolveNavigablePath(fetchable);
            }
        } else {
            fetchablePath = fetchParent.resolveNavigablePath(fetchable);
        }
        FetchTiming fetchTiming = fetchable.getMappedFetchOptions().getTiming();
        boolean joined = fetchable.getMappedFetchOptions().getStyle() == FetchStyle.JOIN;
        boolean explicitFetch = false;
        EntityGraphTraversalState.TraversalResult traversalResult = null;
        final boolean isFetchablePluralAttributeMapping = fetchable instanceof PluralAttributeMapping;
        if (!(fetchable instanceof CollectionPart)) {
            // 'entity graph' takes precedence over 'fetch profile'
            if (entityGraphTraversalState != null) {
                traversalResult = entityGraphTraversalState.traverse(fetchParent, fetchable, isKeyFetchable);
                fetchTiming = traversalResult.getFetchTiming();
                joined = traversalResult.isJoined();
                explicitFetch = true;
            } else if (loadQueryInfluencers.hasEnabledFetchProfiles()) {
                // There is no point in checking the fetch profile if it can't affect this fetchable
                if (fetchTiming != FetchTiming.IMMEDIATE || fetchable.incrementFetchDepth()) {
                    final String fetchableRole = fetchable.getNavigableRole().getFullPath();
                    for (String enabledFetchProfileName : loadQueryInfluencers.getEnabledFetchProfileNames()) {
                        final FetchProfile enabledFetchProfile = creationContext.getSessionFactory().getFetchProfile(enabledFetchProfileName);
                        final org.hibernate.engine.profile.Fetch profileFetch = enabledFetchProfile.getFetchByRole(fetchableRole);
                        if (profileFetch != null) {
                            fetchTiming = FetchTiming.IMMEDIATE;
                            joined = joined || profileFetch.getStyle() == org.hibernate.engine.profile.Fetch.Style.JOIN;
                            explicitFetch = true;
                        }
                    }
                }
            } else if (loadQueryInfluencers.getEnabledCascadingFetchProfile() != null) {
                final CascadeStyle cascadeStyle = ((AttributeMapping) fetchable).getAttributeMetadataAccess().resolveAttributeMetadata(fetchable.findContainingEntityMapping()).getCascadeStyle();
                final CascadingAction cascadingAction = loadQueryInfluencers.getEnabledCascadingFetchProfile().getCascadingAction();
                if (cascadeStyle == null || cascadeStyle.doCascade(cascadingAction)) {
                    fetchTiming = FetchTiming.IMMEDIATE;
                    // In 5.x the CascadeEntityJoinWalker only join fetched the first collection fetch
                    if (isFetchablePluralAttributeMapping) {
                        joined = !hasCollectionJoinFetches;
                    } else {
                        joined = true;
                    }
                }
            }
        }
        final String previousBagRole = currentBagRole;
        final String bagRole;
        if (isFetchablePluralAttributeMapping && ((PluralAttributeMapping) fetchable).getMappedType().getCollectionSemantics() instanceof BagSemantics) {
            bagRole = fetchable.getNavigableRole().getNavigableName();
        } else {
            bagRole = null;
        }
        if (joined && previousBagRole != null && bagRole != null) {
            // Avoid join fetching multiple bags
            joined = false;
        }
        boolean changeFetchDepth = !(fetchable instanceof BasicValuedModelPart) && !(fetchable instanceof EmbeddedAttributeMapping) && !(fetchable instanceof CollectionPart);
        try {
            if (changeFetchDepth) {
                fetchDepth++;
            }
            // There is no need to check for circular fetches if this is an explicit fetch
            if (!explicitFetch && !creationState.isResolvingCircularFetch()) {
                final Fetch biDirectionalFetch = fetchable.resolveCircularFetch(fetchablePath, fetchParent, fetchTiming, creationState);
                if (biDirectionalFetch != null) {
                    fetches.add(biDirectionalFetch);
                    return;
                }
            }
            final Integer maximumFetchDepth = creationContext.getMaximumFetchDepth();
            if (maximumFetchDepth != null) {
                if (fetchDepth == maximumFetchDepth + 1) {
                    joined = false;
                } else if (fetchDepth > maximumFetchDepth + 1) {
                    if (!(fetchable instanceof BasicValuedModelPart) && !(fetchable instanceof EmbeddedAttributeMapping)) {
                        return;
                    }
                }
            }
            if (joined) {
                // For join fetches we remember the currentBagRole so that we can avoid multiple bag fetches
                if (bagRole != null) {
                    currentBagRole = bagRole;
                }
            } else {
                // For non-join fetches, we reset the currentBagRole and set it to the previous value in the finally block
                currentBagRole = null;
            }
            final Fetch fetch = fetchParent.generateFetchableFetch(fetchable, fetchablePath, fetchTiming, joined, null, creationState);
            if (fetch.getTiming() == FetchTiming.IMMEDIATE && isFetchablePluralAttributeMapping) {
                final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) fetchable;
                if (joined) {
                    hasCollectionJoinFetches = true;
                    final TableGroup joinTableGroup = creationState.getFromClauseAccess().getTableGroup(fetchablePath);
                    applyFiltering(querySpec, joinTableGroup, pluralAttributeMapping, creationState);
                    applyOrdering(querySpec, fetchablePath, pluralAttributeMapping, creationState);
                }
            }
            fetches.add(fetch);
        } finally {
            if (changeFetchDepth) {
                fetchDepth--;
            }
            // otherwise we could run into a multiple bag fetch situation
            if (!joined) {
                currentBagRole = previousBagRole;
            }
            if (entityGraphTraversalState != null && traversalResult != null) {
                entityGraphTraversalState.backtrack(traversalResult);
            }
        }
    };
}
Also used : Arrays(java.util.Arrays) CollectionFetch(org.hibernate.sql.results.graph.collection.internal.CollectionFetch) CollectionDomainResult(org.hibernate.sql.results.graph.collection.internal.CollectionDomainResult) GraphSemantic(org.hibernate.graph.GraphSemantic) ResultsHelper.attributeName(org.hibernate.query.results.ResultsHelper.attributeName) TableGroupJoin(org.hibernate.sql.ast.tree.from.TableGroupJoin) CascadingAction(org.hibernate.engine.spi.CascadingAction) EntityValuedModelPart(org.hibernate.metamodel.mapping.EntityValuedModelPart) EntityResultImpl(org.hibernate.sql.results.graph.entity.internal.EntityResultImpl) SqlAstCreationContext(org.hibernate.sql.ast.spi.SqlAstCreationContext) BagSemantics(org.hibernate.collection.spi.BagSemantics) FetchableContainer(org.hibernate.sql.results.graph.FetchableContainer) PluralAttributeMapping(org.hibernate.metamodel.mapping.PluralAttributeMapping) ComparisonPredicate(org.hibernate.sql.ast.tree.predicate.ComparisonPredicate) BiDirectionalFetch(org.hibernate.sql.results.graph.BiDirectionalFetch) ForeignKeyDescriptor(org.hibernate.metamodel.mapping.ForeignKeyDescriptor) Map(java.util.Map) FetchProfile(org.hibernate.engine.profile.FetchProfile) JdbcParameterImpl(org.hibernate.sql.exec.internal.JdbcParameterImpl) ComparisonOperator(org.hibernate.query.sqm.ComparisonOperator) SessionFactoryImplementor(org.hibernate.engine.spi.SessionFactoryImplementor) CollectionPart(org.hibernate.metamodel.mapping.CollectionPart) EntityValuedFetchable(org.hibernate.sql.results.graph.entity.EntityValuedFetchable) InSubQueryPredicate(org.hibernate.sql.ast.tree.predicate.InSubQueryPredicate) Fetchable(org.hibernate.sql.results.graph.Fetchable) TableGroupJoinProducer(org.hibernate.sql.ast.tree.from.TableGroupJoinProducer) LockOptions(org.hibernate.LockOptions) NavigablePath(org.hibernate.query.spi.NavigablePath) AliasCollector(org.hibernate.sql.ast.spi.AliasCollector) DomainResult(org.hibernate.sql.results.graph.DomainResult) Expression(org.hibernate.sql.ast.tree.expression.Expression) OrderByFragment(org.hibernate.metamodel.mapping.ordering.OrderByFragment) SimpleFromClauseAccessImpl(org.hibernate.sql.ast.spi.SimpleFromClauseAccessImpl) SqlExpressionResolver(org.hibernate.sql.ast.spi.SqlExpressionResolver) Objects(java.util.Objects) EntityIdentifierMapping(org.hibernate.metamodel.mapping.EntityIdentifierMapping) SelectStatement(org.hibernate.sql.ast.tree.select.SelectStatement) LoadQueryInfluencers(org.hibernate.engine.spi.LoadQueryInfluencers) List(java.util.List) CascadeStyle(org.hibernate.engine.spi.CascadeStyle) SqlTuple(org.hibernate.sql.ast.tree.expression.SqlTuple) QuerySpec(org.hibernate.sql.ast.tree.select.QuerySpec) SubselectFetch(org.hibernate.engine.spi.SubselectFetch) SimpleForeignKeyDescriptor(org.hibernate.metamodel.mapping.internal.SimpleForeignKeyDescriptor) EmbeddedAttributeMapping(org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping) SqlExpressionResolver.createColumnReferenceKey(org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey) FetchParent(org.hibernate.sql.results.graph.FetchParent) BasicValuedModelPart(org.hibernate.metamodel.mapping.BasicValuedModelPart) InListPredicate(org.hibernate.sql.ast.tree.predicate.InListPredicate) Logger(org.jboss.logging.Logger) ColumnReference(org.hibernate.sql.ast.tree.expression.ColumnReference) ArrayList(java.util.ArrayList) RootGraphImplementor(org.hibernate.graph.spi.RootGraphImplementor) TableReference(org.hibernate.sql.ast.tree.from.TableReference) ModelPart(org.hibernate.metamodel.mapping.ModelPart) Loader(org.hibernate.loader.ast.spi.Loader) BiConsumer(java.util.function.BiConsumer) EntityIdentifierNavigablePath(org.hibernate.query.sqm.spi.EntityIdentifierNavigablePath) SqlAliasBaseManager(org.hibernate.sql.ast.spi.SqlAliasBaseManager) SqlAstCreationState(org.hibernate.sql.ast.spi.SqlAstCreationState) FetchTiming(org.hibernate.engine.FetchTiming) Loadable(org.hibernate.loader.ast.spi.Loadable) Fetch(org.hibernate.sql.results.graph.Fetch) Consumer(java.util.function.Consumer) Restrictable(org.hibernate.metamodel.mapping.Restrictable) EntityGraphTraversalState(org.hibernate.sql.results.graph.EntityGraphTraversalState) FetchStyle(org.hibernate.engine.FetchStyle) StandardEntityGraphTraversalStateImpl(org.hibernate.sql.results.internal.StandardEntityGraphTraversalStateImpl) AbstractMap(java.util.AbstractMap) JdbcParameter(org.hibernate.sql.ast.tree.expression.JdbcParameter) FromClauseAccess(org.hibernate.sql.ast.spi.FromClauseAccess) QueryPart(org.hibernate.sql.ast.tree.select.QueryPart) SqlAstJoinType(org.hibernate.sql.ast.SqlAstJoinType) NaturalIdMapping(org.hibernate.metamodel.mapping.NaturalIdMapping) SqlSelectionImpl(org.hibernate.sql.results.internal.SqlSelectionImpl) NonAggregatedIdentifierMapping(org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping) AttributeMapping(org.hibernate.metamodel.mapping.AttributeMapping) Collections(java.util.Collections) TableGroup(org.hibernate.sql.ast.tree.from.TableGroup) EffectiveEntityGraph(org.hibernate.engine.spi.EffectiveEntityGraph) PluralTableGroup(org.hibernate.sql.ast.tree.from.PluralTableGroup) CascadeStyle(org.hibernate.engine.spi.CascadeStyle) CascadingAction(org.hibernate.engine.spi.CascadingAction) EntityValuedFetchable(org.hibernate.sql.results.graph.entity.EntityValuedFetchable) Fetchable(org.hibernate.sql.results.graph.Fetchable) NavigablePath(org.hibernate.query.spi.NavigablePath) EntityIdentifierNavigablePath(org.hibernate.query.sqm.spi.EntityIdentifierNavigablePath) PluralAttributeMapping(org.hibernate.metamodel.mapping.PluralAttributeMapping) CollectionFetch(org.hibernate.sql.results.graph.collection.internal.CollectionFetch) BiDirectionalFetch(org.hibernate.sql.results.graph.BiDirectionalFetch) SubselectFetch(org.hibernate.engine.spi.SubselectFetch) Fetch(org.hibernate.sql.results.graph.Fetch) EntityValuedModelPart(org.hibernate.metamodel.mapping.EntityValuedModelPart) EmbeddedAttributeMapping(org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping) BiDirectionalFetch(org.hibernate.sql.results.graph.BiDirectionalFetch) CollectionPart(org.hibernate.metamodel.mapping.CollectionPart) FetchProfile(org.hibernate.engine.profile.FetchProfile) TableGroup(org.hibernate.sql.ast.tree.from.TableGroup) PluralTableGroup(org.hibernate.sql.ast.tree.from.PluralTableGroup) BasicValuedModelPart(org.hibernate.metamodel.mapping.BasicValuedModelPart) FetchableContainer(org.hibernate.sql.results.graph.FetchableContainer) EntityValuedFetchable(org.hibernate.sql.results.graph.entity.EntityValuedFetchable) EntityIdentifierNavigablePath(org.hibernate.query.sqm.spi.EntityIdentifierNavigablePath) FetchTiming(org.hibernate.engine.FetchTiming) EntityIdentifierMapping(org.hibernate.metamodel.mapping.EntityIdentifierMapping) BagSemantics(org.hibernate.collection.spi.BagSemantics)

Aggregations

AbstractMap (java.util.AbstractMap)1 ArrayList (java.util.ArrayList)1 Arrays (java.util.Arrays)1 Collections (java.util.Collections)1 List (java.util.List)1 Map (java.util.Map)1 Objects (java.util.Objects)1 BiConsumer (java.util.function.BiConsumer)1 Consumer (java.util.function.Consumer)1 LockOptions (org.hibernate.LockOptions)1 BagSemantics (org.hibernate.collection.spi.BagSemantics)1 FetchStyle (org.hibernate.engine.FetchStyle)1 FetchTiming (org.hibernate.engine.FetchTiming)1 FetchProfile (org.hibernate.engine.profile.FetchProfile)1 CascadeStyle (org.hibernate.engine.spi.CascadeStyle)1 CascadingAction (org.hibernate.engine.spi.CascadingAction)1 EffectiveEntityGraph (org.hibernate.engine.spi.EffectiveEntityGraph)1 LoadQueryInfluencers (org.hibernate.engine.spi.LoadQueryInfluencers)1 SessionFactoryImplementor (org.hibernate.engine.spi.SessionFactoryImplementor)1 SubselectFetch (org.hibernate.engine.spi.SubselectFetch)1