Search in sources :

Example 36 with PluralAttributeMapping

use of org.hibernate.metamodel.mapping.PluralAttributeMapping in project hibernate-orm by hibernate.

the class DynamicFetchBuilderLegacy method buildFetch.

@Override
public Fetch buildFetch(FetchParent parent, NavigablePath fetchPath, JdbcValuesMetadata jdbcResultsMetadata, BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver, DomainResultCreationState domainResultCreationState) {
    final DomainResultCreationStateImpl creationState = ResultsHelper.impl(domainResultCreationState);
    final TableGroup ownerTableGroup = creationState.getFromClauseAccess().findByAlias(ownerTableAlias);
    final AttributeMapping attributeMapping = parent.getReferencedMappingContainer().findContainingEntityMapping().findDeclaredAttributeMapping(fetchableName);
    final TableGroup tableGroup;
    if (attributeMapping instanceof TableGroupJoinProducer) {
        final SqlAliasBase sqlAliasBase = new SqlAliasBaseConstant(tableAlias);
        final TableGroupJoin tableGroupJoin = ((TableGroupJoinProducer) attributeMapping).createTableGroupJoin(fetchPath, ownerTableGroup, tableAlias, SqlAstJoinType.INNER, true, false, s -> sqlAliasBase, creationState.getSqlExpressionResolver(), creationState.getFromClauseAccess(), creationState.getCreationContext());
        ownerTableGroup.addTableGroupJoin(tableGroupJoin);
        creationState.getFromClauseAccess().registerTableGroup(fetchPath, tableGroup = tableGroupJoin.getJoinedGroup());
    } else {
        tableGroup = ownerTableGroup;
    }
    if (columnNames != null) {
        final ForeignKeyDescriptor keyDescriptor;
        if (attributeMapping instanceof PluralAttributeMapping) {
            final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) attributeMapping;
            keyDescriptor = pluralAttributeMapping.getKeyDescriptor();
        } else {
            // Not sure if this fetch builder can also be used with other attribute mappings
            assert attributeMapping instanceof ToOneAttributeMapping;
            final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
            keyDescriptor = toOneAttributeMapping.getForeignKeyDescriptor();
        }
        if (!columnNames.isEmpty()) {
            keyDescriptor.forEachSelectable((selectionIndex, selectableMapping) -> {
                resolveSqlSelection(columnNames.get(selectionIndex), createColumnReferenceKey(tableGroup.resolveTableReference(selectableMapping.getContainingTableExpression()), selectableMapping.getSelectionExpression()), selectableMapping.getJdbcMapping(), jdbcResultsMetadata, domainResultCreationState);
            });
        }
        // We process the fetch builder such that it contains a resultBuilderEntity before calling this method in ResultSetMappingProcessor
        if (resultBuilderEntity != null) {
            return resultBuilderEntity.buildFetch(parent, attributeMapping, jdbcResultsMetadata, creationState);
        }
    }
    try {
        final NavigablePath currentRelativePath = creationState.getCurrentRelativePath();
        final String prefix;
        if (currentRelativePath == null) {
            prefix = "";
        } else {
            prefix = currentRelativePath.getFullPath().replace(ELEMENT_PREFIX, "").replace(INDEX_PREFIX, "") + ".";
        }
        creationState.pushExplicitFetchMementoResolver(relativePath -> {
            if (relativePath.startsWith(prefix)) {
                return findFetchBuilder(relativePath.substring(prefix.length()));
            }
            return null;
        });
        return parent.generateFetchableFetch(attributeMapping, parent.resolveNavigablePath(attributeMapping), FetchTiming.IMMEDIATE, true, null, domainResultCreationState);
    } finally {
        creationState.popExplicitFetchMementoResolver();
    }
}
Also used : TableGroupJoin(org.hibernate.sql.ast.tree.from.TableGroupJoin) DomainResultCreationStateImpl(org.hibernate.query.results.DomainResultCreationStateImpl) TableGroup(org.hibernate.sql.ast.tree.from.TableGroup) TableGroupJoinProducer(org.hibernate.sql.ast.tree.from.TableGroupJoinProducer) NavigablePath(org.hibernate.query.spi.NavigablePath) ToOneAttributeMapping(org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping) ForeignKeyDescriptor(org.hibernate.metamodel.mapping.ForeignKeyDescriptor) PluralAttributeMapping(org.hibernate.metamodel.mapping.PluralAttributeMapping) ToOneAttributeMapping(org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping) AttributeMapping(org.hibernate.metamodel.mapping.AttributeMapping) PluralAttributeMapping(org.hibernate.metamodel.mapping.PluralAttributeMapping) SqlAliasBaseConstant(org.hibernate.sql.ast.spi.SqlAliasBaseConstant) SqlAliasBase(org.hibernate.sql.ast.spi.SqlAliasBase)

Example 37 with PluralAttributeMapping

use of org.hibernate.metamodel.mapping.PluralAttributeMapping 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)

Example 38 with PluralAttributeMapping

use of org.hibernate.metamodel.mapping.PluralAttributeMapping in project hibernate-orm by hibernate.

the class BaseSqmToSqlAstConverter method buildFetch.

private Fetch buildFetch(NavigablePath fetchablePath, FetchParent fetchParent, Fetchable fetchable, FetchTiming fetchTiming, boolean joined, String alias) {
    try {
        final Fetch fetch = fetchParent.generateFetchableFetch(fetchable, fetchablePath, fetchTiming, joined, alias, this);
        if (fetchable instanceof PluralAttributeMapping && fetch.getTiming() == FetchTiming.IMMEDIATE && joined) {
            final TableGroup tableGroup = getFromClauseIndex().getTableGroup(fetchablePath);
            final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) fetchable;
            final Joinable joinable = pluralAttributeMapping.getCollectionDescriptor().getCollectionType().getAssociatedJoinable(getCreationContext().getSessionFactory());
            joinable.applyBaseRestrictions((predicate) -> addCollectionFilterPredicate(tableGroup.getGroupAlias(), predicate), tableGroup, true, getLoadQueryInfluencers().getEnabledFilters(), null, this);
            pluralAttributeMapping.applyBaseManyToManyRestrictions((predicate) -> {
                final TableGroup parentTableGroup = getFromClauseIndex().getTableGroup(fetchParent.getNavigablePath());
                TableGroupJoin pluralTableGroupJoin = null;
                for (TableGroupJoin nestedTableGroupJoin : parentTableGroup.getTableGroupJoins()) {
                    if (nestedTableGroupJoin.getNavigablePath() == fetchablePath) {
                        pluralTableGroupJoin = nestedTableGroupJoin;
                        break;
                    }
                }
                assert pluralTableGroupJoin != null;
                pluralTableGroupJoin.applyPredicate(predicate);
            }, tableGroup, true, getLoadQueryInfluencers().getEnabledFilters(), null, this);
            if (currentQuerySpec().isRoot()) {
                assert tableGroup.getModelPart() == pluralAttributeMapping;
                applyOrdering(tableGroup, pluralAttributeMapping);
            }
        }
        return fetch;
    } catch (RuntimeException e) {
        throw new HibernateException(String.format(Locale.ROOT, "Could not generate fetch : %s -> %s", fetchParent.getNavigablePath(), fetchable.getFetchableName()), e);
    }
}
Also used : Fetch(org.hibernate.sql.results.graph.Fetch) TableGroupJoin(org.hibernate.sql.ast.tree.from.TableGroupJoin) 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) HibernateException(org.hibernate.HibernateException) Joinable(org.hibernate.persister.entity.Joinable) PluralAttributeMapping(org.hibernate.metamodel.mapping.PluralAttributeMapping)

Example 39 with PluralAttributeMapping

use of org.hibernate.metamodel.mapping.PluralAttributeMapping in project hibernate-orm by hibernate.

the class SqmCteTable method createEntityTable.

public static SqmCteTable createEntityTable(String cteName, EntityMappingType entityDescriptor) {
    return new SqmCteTable(cteName, sqmCteTable -> {
        final int numberOfColumns = entityDescriptor.getIdentifierMapping().getJdbcTypeCount();
        final List<SqmCteTableColumn> columns = new ArrayList<>(numberOfColumns);
        final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
        final String idName;
        if (identifierMapping instanceof SingleAttributeIdentifierMapping) {
            idName = ((SingleAttributeIdentifierMapping) identifierMapping).getAttributeName();
        } else {
            idName = "id";
        }
        columns.add(new SqmCteTableColumn(sqmCteTable, idName, identifierMapping));
        final EntityDiscriminatorMapping discriminatorMapping = entityDescriptor.getDiscriminatorMapping();
        if (discriminatorMapping != null && discriminatorMapping.isPhysical() && !discriminatorMapping.isFormula()) {
            columns.add(new SqmCteTableColumn(sqmCteTable, "class", discriminatorMapping));
        }
        // Collect all columns for all entity subtype attributes
        entityDescriptor.visitSubTypeAttributeMappings(attribute -> {
            if (!(attribute instanceof PluralAttributeMapping)) {
                columns.add(new SqmCteTableColumn(sqmCteTable, attribute.getAttributeName(), attribute));
            }
        });
        // We add a special row number column that we can use to identify and join rows
        columns.add(new SqmCteTableColumn(sqmCteTable, "rn_", entityDescriptor.getEntityPersister().getFactory().getTypeConfiguration().getBasicTypeForJavaType(Integer.class)));
        return columns;
    });
}
Also used : ArrayList(java.util.ArrayList) EntityIdentifierMapping(org.hibernate.metamodel.mapping.EntityIdentifierMapping) PluralAttributeMapping(org.hibernate.metamodel.mapping.PluralAttributeMapping) SingleAttributeIdentifierMapping(org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping) EntityDiscriminatorMapping(org.hibernate.metamodel.mapping.EntityDiscriminatorMapping)

Example 40 with PluralAttributeMapping

use of org.hibernate.metamodel.mapping.PluralAttributeMapping in project hibernate-orm by hibernate.

the class EmbeddableAccessTests method verifyRuntimeModel.

@Test
public void verifyRuntimeModel(SessionFactoryScope scope) {
    final RuntimeMetamodels runtimeMetamodels = scope.getSessionFactory().getRuntimeMetamodels();
    final EntityMappingType personDescriptor = runtimeMetamodels.getEntityMappingType(Person.class);
    // Person defines FIELD access, while Name uses PROPERTY
    // - if we find the property annotations, the attribute names will be
    // `firstName` and `lastName`, and the columns `first_name` and `last_name`
    // - otherwise, we have property and column names being `first` and `last`
    final EmbeddableMappingType nameEmbeddable = ((EmbeddedAttributeMapping) personDescriptor.findAttributeMapping("name")).getEmbeddableTypeDescriptor();
    assertThat(nameEmbeddable.getNumberOfAttributeMappings()).isEqualTo(2);
    final AttributeMapping nameFirst = nameEmbeddable.getAttributeMapping(0);
    final AttributeMapping nameLast = nameEmbeddable.getAttributeMapping(1);
    assertThat(nameFirst.getAttributeName()).isEqualTo("firstName");
    assertThat(nameLast.getAttributeName()).isEqualTo("lastName");
    final PluralAttributeMapping aliasesAttribute = (PluralAttributeMapping) personDescriptor.findAttributeMapping("aliases");
    final EmbeddableMappingType aliasEmbeddable = ((EmbeddedCollectionPart) aliasesAttribute.getElementDescriptor()).getEmbeddableTypeDescriptor();
    assertThat(aliasEmbeddable.getNumberOfAttributeMappings()).isEqualTo(2);
    final AttributeMapping aliasFirst = nameEmbeddable.getAttributeMapping(0);
    final AttributeMapping aliasLast = nameEmbeddable.getAttributeMapping(1);
    assertThat(aliasFirst.getAttributeName()).isEqualTo("firstName");
    assertThat(aliasLast.getAttributeName()).isEqualTo("lastName");
}
Also used : EmbeddedAttributeMapping(org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping) EmbeddedCollectionPart(org.hibernate.metamodel.mapping.internal.EmbeddedCollectionPart) PluralAttributeMapping(org.hibernate.metamodel.mapping.PluralAttributeMapping) AttributeMapping(org.hibernate.metamodel.mapping.AttributeMapping) EmbeddedAttributeMapping(org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping) PluralAttributeMapping(org.hibernate.metamodel.mapping.PluralAttributeMapping) RuntimeMetamodels(org.hibernate.metamodel.RuntimeMetamodels) EmbeddableMappingType(org.hibernate.metamodel.mapping.EmbeddableMappingType) EntityMappingType(org.hibernate.metamodel.mapping.EntityMappingType) Test(org.junit.jupiter.api.Test)

Aggregations

PluralAttributeMapping (org.hibernate.metamodel.mapping.PluralAttributeMapping)40 TableGroup (org.hibernate.sql.ast.tree.from.TableGroup)23 NavigablePath (org.hibernate.query.spi.NavigablePath)16 PluralTableGroup (org.hibernate.sql.ast.tree.from.PluralTableGroup)15 ArrayList (java.util.ArrayList)12 QuerySpec (org.hibernate.sql.ast.tree.select.QuerySpec)12 TableGroupJoin (org.hibernate.sql.ast.tree.from.TableGroupJoin)11 CollectionPart (org.hibernate.metamodel.mapping.CollectionPart)9 ModelPart (org.hibernate.metamodel.mapping.ModelPart)9 CorrelatedPluralTableGroup (org.hibernate.sql.ast.tree.from.CorrelatedPluralTableGroup)9 CorrelatedTableGroup (org.hibernate.sql.ast.tree.from.CorrelatedTableGroup)9 LazyTableGroup (org.hibernate.sql.ast.tree.from.LazyTableGroup)9 QueryPartTableGroup (org.hibernate.sql.ast.tree.from.QueryPartTableGroup)9 VirtualTableGroup (org.hibernate.sql.ast.tree.from.VirtualTableGroup)9 SelectStatement (org.hibernate.sql.ast.tree.select.SelectStatement)9 FetchTiming (org.hibernate.engine.FetchTiming)7 SessionFactoryImplementor (org.hibernate.engine.spi.SessionFactoryImplementor)7 SqlAstQueryPartProcessingStateImpl (org.hibernate.query.sqm.sql.internal.SqlAstQueryPartProcessingStateImpl)7 SqlSelectionImpl (org.hibernate.sql.results.internal.SqlSelectionImpl)7 Map (java.util.Map)6