use of org.hibernate.metamodel.mapping.PluralAttributeMapping 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);
}
}
};
}
use of org.hibernate.metamodel.mapping.PluralAttributeMapping in project hibernate-orm by hibernate.
the class LoaderSelectBuilder method applySubSelectRestriction.
private void applySubSelectRestriction(QuerySpec querySpec, NavigablePath rootNavigablePath, TableGroup rootTableGroup, SubselectFetch subselect, LoaderSqlAstCreationState sqlAstCreationState) {
final SqlAstCreationContext sqlAstCreationContext = sqlAstCreationState.getCreationContext();
final SessionFactoryImplementor sessionFactory = sqlAstCreationContext.getSessionFactory();
assert loadable instanceof PluralAttributeMapping;
final PluralAttributeMapping attributeMapping = (PluralAttributeMapping) loadable;
final ForeignKeyDescriptor fkDescriptor = attributeMapping.getKeyDescriptor();
final NavigablePath navigablePath = rootNavigablePath.append(attributeMapping.getAttributeName());
final Expression fkExpression;
final int jdbcTypeCount = fkDescriptor.getJdbcTypeCount();
if (jdbcTypeCount == 1) {
assert fkDescriptor instanceof SimpleForeignKeyDescriptor;
final SimpleForeignKeyDescriptor simpleFkDescriptor = (SimpleForeignKeyDescriptor) fkDescriptor;
final TableReference tableReference = rootTableGroup.resolveTableReference(navigablePath, simpleFkDescriptor.getContainingTableExpression());
fkExpression = sqlAstCreationState.getSqlExpressionResolver().resolveSqlExpression(createColumnReferenceKey(tableReference, simpleFkDescriptor.getSelectionExpression()), sqlAstProcessingState -> new ColumnReference(tableReference, simpleFkDescriptor.getSelectionExpression(), false, null, null, simpleFkDescriptor.getJdbcMapping(), this.creationContext.getSessionFactory()));
} else {
final List<ColumnReference> columnReferences = new ArrayList<>(jdbcTypeCount);
fkDescriptor.forEachSelectable((columnIndex, selection) -> {
final TableReference tableReference = rootTableGroup.resolveTableReference(navigablePath, selection.getContainingTableExpression());
columnReferences.add((ColumnReference) sqlAstCreationState.getSqlExpressionResolver().resolveSqlExpression(createColumnReferenceKey(tableReference, selection.getSelectionExpression()), sqlAstProcessingState -> new ColumnReference(tableReference, selection, this.creationContext.getSessionFactory())));
});
fkExpression = new SqlTuple(columnReferences, fkDescriptor);
}
querySpec.applyPredicate(new InSubQueryPredicate(fkExpression, generateSubSelect(attributeMapping, rootTableGroup, subselect, jdbcTypeCount, sqlAstCreationState, sessionFactory), false));
}
use of org.hibernate.metamodel.mapping.PluralAttributeMapping in project hibernate-orm by hibernate.
the class LoaderSelectBuilder method generateSelect.
private SelectStatement generateSelect(SubselectFetch subselect) {
assert loadable instanceof PluralAttributeMapping;
final PluralAttributeMapping attributeMapping = (PluralAttributeMapping) loadable;
final QuerySpec rootQuerySpec = new QuerySpec(true);
final NavigablePath rootNavigablePath = new NavigablePath(loadable.getRootPathName());
// We need to initialize the acronymMap based on subselect.getLoadingSqlAst() to avoid alias collisions
final Map<String, TableReference> tableReferences = AliasCollector.getTableReferences(subselect.getLoadingSqlAst());
final LoaderSqlAstCreationState sqlAstCreationState = new LoaderSqlAstCreationState(rootQuerySpec, new SqlAliasBaseManager(tableReferences.keySet()), new SimpleFromClauseAccessImpl(), lockOptions, this::visitFetches, numberOfKeysToLoad > 1, creationContext);
final TableGroup rootTableGroup = loadable.createRootTableGroup(true, rootNavigablePath, null, () -> rootQuerySpec::applyPredicate, sqlAstCreationState, creationContext);
rootQuerySpec.getFromClause().addRoot(rootTableGroup);
sqlAstCreationState.getFromClauseAccess().registerTableGroup(rootNavigablePath, rootTableGroup);
registerPluralTableGroupParts(sqlAstCreationState.getFromClauseAccess(), rootTableGroup);
// generate and apply the restriction
applySubSelectRestriction(rootQuerySpec, rootNavigablePath, rootTableGroup, subselect, sqlAstCreationState);
// NOTE : no need to check - we are explicitly processing a plural-attribute
applyFiltering(rootQuerySpec, rootTableGroup, attributeMapping, sqlAstCreationState);
applyOrdering(rootTableGroup, attributeMapping);
return new SelectStatement(rootQuerySpec, List.of(new CollectionDomainResult(rootNavigablePath, attributeMapping, null, rootTableGroup, sqlAstCreationState)));
}
use of org.hibernate.metamodel.mapping.PluralAttributeMapping in project hibernate-orm by hibernate.
the class EmbeddableMappingTypeImpl method forEachJdbcValue.
@Override
public int forEachJdbcValue(Object value, Clause clause, int offset, JdbcValuesConsumer consumer, SharedSessionContractImplementor session) {
int span = 0;
for (int i = 0; i < attributeMappings.size(); i++) {
final AttributeMapping attributeMapping = attributeMappings.get(i);
if (attributeMapping instanceof PluralAttributeMapping) {
continue;
}
final Object o = attributeMapping.getPropertyAccess().getGetter().get(value);
span += attributeMapping.forEachJdbcValue(o, clause, span + offset, consumer, session);
}
return span;
}
use of org.hibernate.metamodel.mapping.PluralAttributeMapping in project hibernate-orm by hibernate.
the class EmbeddedForeignKeyDescriptor method createDomainResult.
private <T> DomainResult<T> createDomainResult(NavigablePath navigablePath, TableGroup tableGroup, String resultVariable, String columnContainingTable, EmbeddableValuedModelPart modelPart, DomainResultCreationState creationState) {
final NavigablePath fkNavigablePath = navigablePath.append(getPartName());
final NavigablePath resultNavigablePath;
if (associationKey.getTable().equals(columnContainingTable)) {
final ModelPartContainer parentModelPart = tableGroup.getModelPart();
if (parentModelPart instanceof PluralAttributeMapping) {
if (((PluralAttributeMapping) parentModelPart).getIndexDescriptor() == null) {
resultNavigablePath = navigablePath.append(CollectionPart.Nature.ELEMENT.getName()).append(getPartName());
} else {
resultNavigablePath = navigablePath.append(CollectionPart.Nature.INDEX.getName()).append(getPartName());
}
} else {
resultNavigablePath = navigablePath.append(getPartName());
}
} else {
resultNavigablePath = navigablePath.append(getPartName());
}
final TableGroup fkTableGroup = creationState.getSqlAstCreationState().getFromClauseAccess().resolveTableGroup(resultNavigablePath, np -> {
final TableGroupJoin tableGroupJoin = modelPart.createTableGroupJoin(resultNavigablePath, tableGroup, null, SqlAstJoinType.INNER, true, false, creationState.getSqlAstCreationState());
tableGroup.addTableGroupJoin(tableGroupJoin);
return tableGroupJoin.getJoinedGroup();
});
if (fkNavigablePath != resultNavigablePath) {
creationState.getSqlAstCreationState().getFromClauseAccess().resolveTableGroup(fkNavigablePath, np -> fkTableGroup);
}
final Nature currentForeignKeyResolvingKey = creationState.getCurrentlyResolvingForeignKeyPart();
try {
creationState.setCurrentlyResolvingForeignKeyPart(keySide.getModelPart() == modelPart ? Nature.KEY : Nature.TARGET);
return new EmbeddableForeignKeyResultImpl<>(resultNavigablePath, modelPart, resultVariable, creationState);
} finally {
creationState.setCurrentlyResolvingForeignKeyPart(currentForeignKeyResolvingKey);
}
}
Aggregations