Search in sources :

Example 1 with CollectionClassification

use of org.hibernate.metamodel.CollectionClassification in project hibernate-orm by hibernate.

the class CollectionBinder method getCollectionBinder.

/**
 * collection binder factory
 */
public static CollectionBinder getCollectionBinder(XProperty property, boolean isHibernateExtensionMapping, MetadataBuildingContext buildingContext) {
    final CollectionType typeAnnotation = HCANNHelper.findAnnotation(property, CollectionType.class);
    final CollectionBinder binder;
    if (typeAnnotation != null) {
        binder = createBinderFromCustomTypeAnnotation(property, typeAnnotation, buildingContext);
        // todo (6.0) - technically, these should no longer be needed
        binder.explicitType = typeAnnotation.type().getName();
        for (Parameter param : typeAnnotation.parameters()) {
            binder.explicitTypeParameters.setProperty(param.name(), param.value());
        }
    } else {
        final CollectionClassification classification = determineCollectionClassification(property, buildingContext);
        final CollectionTypeRegistrationDescriptor typeRegistration = buildingContext.getMetadataCollector().findCollectionTypeRegistration(classification);
        if (typeRegistration != null) {
            binder = createBinderFromTypeRegistration(property, classification, typeRegistration, buildingContext);
        } else {
            binder = createBinderFromProperty(property, buildingContext);
        }
    }
    binder.setIsHibernateExtensionMapping(isHibernateExtensionMapping);
    return binder;
}
Also used : CollectionClassification(org.hibernate.metamodel.CollectionClassification) CollectionTypeRegistrationDescriptor(org.hibernate.boot.spi.InFlightMetadataCollector.CollectionTypeRegistrationDescriptor) UserCollectionType(org.hibernate.usertype.UserCollectionType) CollectionType(org.hibernate.annotations.CollectionType) Parameter(org.hibernate.annotations.Parameter)

Example 2 with CollectionClassification

use of org.hibernate.metamodel.CollectionClassification in project hibernate-orm by hibernate.

the class BaseSqmToSqlAstConverter method addFetch.

public void addFetch(List<Fetch> fetches, FetchParent fetchParent, Fetchable fetchable, Boolean isKeyFetchable) {
    final NavigablePath resolvedNavigablePath = fetchParent.resolveNavigablePath(fetchable);
    final String alias;
    FetchTiming fetchTiming = fetchable.getMappedFetchOptions().getTiming();
    boolean joined = false;
    EntityGraphTraversalState.TraversalResult traversalResult = null;
    final FromClauseIndex fromClauseIndex = getFromClauseIndex();
    final SqmAttributeJoin<?, ?> fetchedJoin = fromClauseIndex.findFetchedJoinByPath(resolvedNavigablePath);
    boolean explicitFetch = false;
    final NavigablePath fetchablePath;
    if (fetchedJoin != null) {
        fetchablePath = fetchedJoin.getNavigablePath();
        // there should be a TableGroupJoin registered for this `fetchablePath` already
        assert fromClauseIndex.getTableGroup(fetchedJoin.getNavigablePath()) != null;
        if (fetchedJoin.isFetched()) {
            fetchTiming = FetchTiming.IMMEDIATE;
        }
        joined = true;
        alias = fetchedJoin.getExplicitAlias();
        explicitFetch = true;
    } else {
        fetchablePath = resolvedNavigablePath;
        // there was not an explicit fetch in the SQM
        alias = null;
        if (!(fetchable instanceof CollectionPart)) {
            if (entityGraphTraversalState != null) {
                traversalResult = entityGraphTraversalState.traverse(fetchParent, fetchable, isKeyFetchable);
                fetchTiming = traversalResult.getFetchTiming();
                joined = traversalResult.isJoined();
                explicitFetch = true;
            } else if (getLoadQueryInfluencers().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 : getLoadQueryInfluencers().getEnabledFetchProfileNames()) {
                        final FetchProfile enabledFetchProfile = getCreationContext().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;
                            if (currentBagRole != null && fetchable instanceof PluralAttributeMapping) {
                                final CollectionClassification collectionClassification = ((PluralAttributeMapping) fetchable).getMappedType().getCollectionSemantics().getCollectionClassification();
                                if (collectionClassification == CollectionClassification.BAG) {
                                    // To avoid a MultipleBagFetchException due to fetch profiles in a circular model,
                                    // we skip join fetching in case we encounter an existing bag role
                                    joined = false;
                                }
                            }
                        }
                    }
                }
            }
        }
        // final TableGroup existingJoinedGroup = fromClauseIndex.findTableGroup( fetchablePath );
        // if ( existingJoinedGroup != null ) {
        // we can use this to trigger the fetch from the joined group.
        // todo (6.0) : do we want to do this though?
        // On the positive side it would allow EntityGraph to use the existing TableGroup.  But that ties in
        // to the discussion above regarding how to handle eager and EntityGraph (JOIN versus SELECT).
        // Can be problematic if the existing one is restricted
        // fetchTiming = FetchTiming.IMMEDIATE;
        // }
        // lastly, account for any app-defined max-fetch-depth
        final Integer maxDepth = getCreationContext().getMaximumFetchDepth();
        if (maxDepth != null) {
            if (fetchDepth >= maxDepth) {
                joined = false;
            }
        }
        if (joined && fetchable instanceof TableGroupJoinProducer) {
            TableGroupJoinProducer tableGroupJoinProducer = (TableGroupJoinProducer) fetchable;
            fromClauseIndex.resolveTableGroup(fetchablePath, np -> {
                // generate the join
                final TableGroup lhs = fromClauseIndex.getTableGroup(fetchParent.getNavigablePath());
                final TableGroupJoin tableGroupJoin = ((TableGroupJoinProducer) fetchable).createTableGroupJoin(fetchablePath, lhs, alias, tableGroupJoinProducer.getDefaultSqlAstJoinType(lhs), true, false, BaseSqmToSqlAstConverter.this);
                lhs.addTableGroupJoin(tableGroupJoin);
                return tableGroupJoin.getJoinedGroup();
            });
        }
    }
    final boolean incrementFetchDepth = fetchable.incrementFetchDepth();
    try {
        if (incrementFetchDepth) {
            fetchDepth++;
        }
        // There is no need to check for circular fetches if this is an explicit fetch
        if (!explicitFetch && !isResolvingCircularFetch()) {
            final Fetch biDirectionalFetch = fetchable.resolveCircularFetch(fetchablePath, fetchParent, fetchTiming, this);
            if (biDirectionalFetch != null) {
                fetches.add(biDirectionalFetch);
                return;
            }
        }
        final Fetch fetch = buildFetch(fetchablePath, fetchParent, fetchable, fetchTiming, joined, alias);
        if (fetch != null) {
            if (fetch.getTiming() == FetchTiming.IMMEDIATE && fetchable instanceof PluralAttributeMapping) {
                final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) fetchable;
                final CollectionClassification collectionClassification = pluralAttributeMapping.getMappedType().getCollectionSemantics().getCollectionClassification();
                if (collectionClassification == CollectionClassification.BAG) {
                    if (currentBagRole != null) {
                        throw new MultipleBagFetchException(Arrays.asList(currentBagRole, fetchable.getNavigableRole().getNavigableName()));
                    }
                    currentBagRole = fetchable.getNavigableRole().getNavigableName();
                }
            }
            fetches.add(fetch);
        }
    } finally {
        if (incrementFetchDepth) {
            fetchDepth--;
        }
        if (entityGraphTraversalState != null && traversalResult != null) {
            entityGraphTraversalState.backtrack(traversalResult);
        }
    }
}
Also used : EntityGraphTraversalState(org.hibernate.sql.results.graph.EntityGraphTraversalState) FetchProfile(org.hibernate.engine.profile.FetchProfile) NavigablePath(org.hibernate.query.spi.NavigablePath) TableGroupJoinProducer(org.hibernate.sql.ast.tree.from.TableGroupJoinProducer) VirtualTableGroup(org.hibernate.sql.ast.tree.from.VirtualTableGroup) LazyTableGroup(org.hibernate.sql.ast.tree.from.LazyTableGroup) TableGroup(org.hibernate.sql.ast.tree.from.TableGroup) CorrelatedTableGroup(org.hibernate.sql.ast.tree.from.CorrelatedTableGroup) CorrelatedPluralTableGroup(org.hibernate.sql.ast.tree.from.CorrelatedPluralTableGroup) PluralTableGroup(org.hibernate.sql.ast.tree.from.PluralTableGroup) QueryPartTableGroup(org.hibernate.sql.ast.tree.from.QueryPartTableGroup) PluralAttributeMapping(org.hibernate.metamodel.mapping.PluralAttributeMapping) Fetch(org.hibernate.sql.results.graph.Fetch) BigInteger(java.math.BigInteger) TableGroupJoin(org.hibernate.sql.ast.tree.from.TableGroupJoin) CollectionClassification(org.hibernate.metamodel.CollectionClassification) FetchTiming(org.hibernate.engine.FetchTiming) EntityCollectionPart(org.hibernate.metamodel.mapping.internal.EntityCollectionPart) CollectionPart(org.hibernate.metamodel.mapping.CollectionPart) EmbeddedCollectionPart(org.hibernate.metamodel.mapping.internal.EmbeddedCollectionPart) MultipleBagFetchException(org.hibernate.loader.MultipleBagFetchException)

Aggregations

CollectionClassification (org.hibernate.metamodel.CollectionClassification)2 BigInteger (java.math.BigInteger)1 CollectionType (org.hibernate.annotations.CollectionType)1 Parameter (org.hibernate.annotations.Parameter)1 CollectionTypeRegistrationDescriptor (org.hibernate.boot.spi.InFlightMetadataCollector.CollectionTypeRegistrationDescriptor)1 FetchTiming (org.hibernate.engine.FetchTiming)1 FetchProfile (org.hibernate.engine.profile.FetchProfile)1 MultipleBagFetchException (org.hibernate.loader.MultipleBagFetchException)1 CollectionPart (org.hibernate.metamodel.mapping.CollectionPart)1 PluralAttributeMapping (org.hibernate.metamodel.mapping.PluralAttributeMapping)1 EmbeddedCollectionPart (org.hibernate.metamodel.mapping.internal.EmbeddedCollectionPart)1 EntityCollectionPart (org.hibernate.metamodel.mapping.internal.EntityCollectionPart)1 NavigablePath (org.hibernate.query.spi.NavigablePath)1 CorrelatedPluralTableGroup (org.hibernate.sql.ast.tree.from.CorrelatedPluralTableGroup)1 CorrelatedTableGroup (org.hibernate.sql.ast.tree.from.CorrelatedTableGroup)1 LazyTableGroup (org.hibernate.sql.ast.tree.from.LazyTableGroup)1 PluralTableGroup (org.hibernate.sql.ast.tree.from.PluralTableGroup)1 QueryPartTableGroup (org.hibernate.sql.ast.tree.from.QueryPartTableGroup)1 TableGroup (org.hibernate.sql.ast.tree.from.TableGroup)1 TableGroupJoin (org.hibernate.sql.ast.tree.from.TableGroupJoin)1