use of org.hibernate.metamodel.mapping.EmbeddableValuedModelPart in project hibernate-orm by hibernate.
the class ToOneAttributeMapping method createRootTableGroupJoin.
@Override
public LazyTableGroup createRootTableGroupJoin(NavigablePath navigablePath, TableGroup lhs, String explicitSourceAlias, SqlAstJoinType requestedJoinType, boolean fetched, Consumer<Predicate> predicateConsumer, SqlAliasBaseGenerator aliasBaseGenerator, SqlExpressionResolver sqlExpressionResolver, FromClauseAccess fromClauseAccess, SqlAstCreationContext creationContext) {
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase(sqlAliasStem);
final SqlAstJoinType joinType;
if (requestedJoinType == null) {
joinType = SqlAstJoinType.INNER;
} else {
joinType = requestedJoinType;
}
final boolean canUseInnerJoin = joinType == SqlAstJoinType.INNER || lhs.canUseInnerJoins() && !isNullable;
TableGroup realParentTableGroup = lhs;
while (realParentTableGroup.getModelPart() instanceof EmbeddableValuedModelPart) {
realParentTableGroup = fromClauseAccess.findTableGroup(realParentTableGroup.getNavigablePath().getParent());
}
final TableGroupProducer tableGroupProducer;
if (realParentTableGroup instanceof CorrelatedTableGroup) {
// If the parent is a correlated table group, we can't refer to columns of the table in the outer query,
// because the context in which a column is used could be an aggregate function.
// Using a parent column in such a case would lead to an error if the parent query lacks a proper group by
tableGroupProducer = entityMappingType;
} else {
tableGroupProducer = this;
}
final LazyTableGroup lazyTableGroup = new LazyTableGroup(canUseInnerJoin, navigablePath, fetched, () -> createTableGroupInternal(canUseInnerJoin, navigablePath, fetched, null, sqlAliasBase, sqlExpressionResolver, creationContext), (np, tableExpression) -> {
if (!canUseParentTableGroup || tableGroupProducer != ToOneAttributeMapping.this) {
return false;
}
NavigablePath path = np.getParent();
// Fast path
if (path != null && navigablePath.equals(path)) {
return targetKeyPropertyNames.contains(np.getUnaliasedLocalName()) && identifyingColumnsTableExpression.equals(tableExpression);
}
final StringBuilder sb = new StringBuilder(np.getFullPath().length());
sb.append(np.getUnaliasedLocalName());
while (path != null && !navigablePath.equals(path)) {
sb.insert(0, '.');
sb.insert(0, path.getUnaliasedLocalName());
path = path.getParent();
}
return path != null && navigablePath.equals(path) && targetKeyPropertyNames.contains(sb.toString()) && identifyingColumnsTableExpression.equals(tableExpression);
}, tableGroupProducer, explicitSourceAlias, sqlAliasBase, creationContext.getSessionFactory(), lhs);
if (predicateConsumer != null) {
final TableReference lhsTableReference = lhs.resolveTableReference(navigablePath, identifyingColumnsTableExpression);
lazyTableGroup.setTableGroupInitializerCallback(tableGroup -> predicateConsumer.accept(foreignKeyDescriptor.generateJoinPredicate(sideNature == ForeignKeyDescriptor.Nature.TARGET ? lhsTableReference : tableGroup.getPrimaryTableReference(), sideNature == ForeignKeyDescriptor.Nature.TARGET ? tableGroup.getPrimaryTableReference() : lhsTableReference, sqlExpressionResolver, creationContext)));
}
if (realParentTableGroup instanceof CorrelatedTableGroup) {
// Force initialization of the underlying table group join to retain cardinality
lazyTableGroup.getPrimaryTableReference();
} else {
initializeIfNeeded(lhs, requestedJoinType, lazyTableGroup);
}
return lazyTableGroup;
}
use of org.hibernate.metamodel.mapping.EmbeddableValuedModelPart in project hibernate-orm by hibernate.
the class ToOneAttributeMapping method createTableGroupJoin.
@Override
public TableGroupJoin createTableGroupJoin(NavigablePath navigablePath, TableGroup lhs, String explicitSourceAlias, SqlAstJoinType requestedJoinType, boolean fetched, boolean addsPredicate, SqlAliasBaseGenerator aliasBaseGenerator, SqlExpressionResolver sqlExpressionResolver, FromClauseAccess fromClauseAccess, SqlAstCreationContext creationContext) {
// This is vital for the map key property check that comes next
assert !(lhs instanceof PluralTableGroup);
TableGroup parentTableGroup = lhs;
ModelPartContainer parentContainer = lhs.getModelPart();
StringBuilder embeddablePathSb = null;
// Traverse up embeddable table groups until we find a table group for a collection part
while (!(parentContainer instanceof CollectionPart)) {
if (parentContainer instanceof EmbeddableValuedModelPart) {
if (embeddablePathSb == null) {
embeddablePathSb = new StringBuilder();
}
embeddablePathSb.insert(0, parentContainer.getPartName() + ".");
parentTableGroup = fromClauseAccess.findTableGroup(parentTableGroup.getNavigablePath().getParent());
parentContainer = parentTableGroup.getModelPart();
} else {
break;
}
}
final SqlAstJoinType joinType;
if (requestedJoinType == null) {
joinType = SqlAstJoinType.INNER;
} else {
joinType = requestedJoinType;
}
// we check if this attribute is the map key property to reuse the existing index table group
if (CollectionPart.Nature.ELEMENT.getName().equals(parentTableGroup.getNavigablePath().getUnaliasedLocalName()) && !addsPredicate && (joinType == SqlAstJoinType.INNER || joinType == SqlAstJoinType.LEFT)) {
final PluralTableGroup pluralTableGroup = (PluralTableGroup) fromClauseAccess.findTableGroup(parentTableGroup.getNavigablePath().getParent());
final String indexPropertyName = pluralTableGroup.getModelPart().getIndexMetadata().getIndexPropertyName();
final String pathName;
if (embeddablePathSb != null) {
pathName = embeddablePathSb.append(getAttributeName()).toString();
} else {
pathName = getAttributeName();
}
if (pathName.equals(indexPropertyName)) {
final TableGroup indexTableGroup = pluralTableGroup.getIndexTableGroup();
// If this is the map key property, we can reuse the index table group
initializeIfNeeded(lhs, requestedJoinType, indexTableGroup);
return new TableGroupJoin(navigablePath, joinType, new MappedByTableGroup(navigablePath, this, indexTableGroup, fetched, pluralTableGroup, (np, tableExpression) -> {
if (!canUseParentTableGroup) {
return false;
}
NavigablePath path = np.getParent();
// Fast path
if (path != null && navigablePath.equals(path)) {
return targetKeyPropertyNames.contains(np.getUnaliasedLocalName()) && identifyingColumnsTableExpression.equals(tableExpression);
}
final StringBuilder sb = new StringBuilder(np.getFullPath().length());
sb.append(np.getUnaliasedLocalName());
while (path != null && !navigablePath.equals(path)) {
sb.insert(0, '.');
sb.insert(0, path.getUnaliasedLocalName());
path = path.getParent();
}
return path != null && navigablePath.equals(path) && targetKeyPropertyNames.contains(sb.toString()) && identifyingColumnsTableExpression.equals(tableExpression);
}), null);
}
}
final LazyTableGroup lazyTableGroup = createRootTableGroupJoin(navigablePath, lhs, explicitSourceAlias, requestedJoinType, fetched, null, aliasBaseGenerator, sqlExpressionResolver, fromClauseAccess, creationContext);
final TableGroupJoin join = new TableGroupJoin(navigablePath, joinType, lazyTableGroup, null);
final TableReference lhsTableReference = lhs.resolveTableReference(navigablePath, identifyingColumnsTableExpression);
lazyTableGroup.setTableGroupInitializerCallback(tableGroup -> join.applyPredicate(foreignKeyDescriptor.generateJoinPredicate(sideNature == ForeignKeyDescriptor.Nature.TARGET ? lhsTableReference : tableGroup.getPrimaryTableReference(), sideNature == ForeignKeyDescriptor.Nature.TARGET ? tableGroup.getPrimaryTableReference() : lhsTableReference, sqlExpressionResolver, creationContext)));
return join;
}
use of org.hibernate.metamodel.mapping.EmbeddableValuedModelPart in project hibernate-orm by hibernate.
the class MappingModelCreationHelper method interpretPluralAttributeMappingKeyDescriptor.
private static void interpretPluralAttributeMappingKeyDescriptor(PluralAttributeMappingImpl attributeMapping, Collection bootValueMapping, CollectionPersister collectionDescriptor, ManagedMappingType declaringType, Dialect dialect, MappingModelCreationProcess creationProcess) {
ModelPart attributeMappingSubPart = null;
if (!StringHelper.isEmpty(collectionDescriptor.getMappedByProperty())) {
attributeMappingSubPart = ((ModelPartContainer) attributeMapping.getElementDescriptor().getPartMappingType()).findSubPart(collectionDescriptor.getMappedByProperty(), null);
}
if (attributeMappingSubPart instanceof ToOneAttributeMapping) {
final ToOneAttributeMapping referencedAttributeMapping = (ToOneAttributeMapping) attributeMappingSubPart;
setReferencedAttributeForeignKeyDescriptor(attributeMapping, referencedAttributeMapping, referencedAttributeMapping.findContainingEntityMapping().getEntityPersister(), collectionDescriptor.getMappedByProperty(), dialect, creationProcess);
return;
}
final KeyValue bootValueMappingKey = bootValueMapping.getKey();
final Type keyType = bootValueMappingKey.getType();
final ModelPart fkTarget;
final String lhsPropertyName = collectionDescriptor.getCollectionType().getLHSPropertyName();
final boolean isReferenceToPrimaryKey = lhsPropertyName == null;
final ManagedMappingType keyDeclaringType;
if (collectionDescriptor.getElementType().isEntityType()) {
keyDeclaringType = ((QueryableCollection) collectionDescriptor).getElementPersister();
} else {
// This is not "really correct" but it is as good as it gets.
// The key declaring type serves as declaring type for the inverse model part of a FK.
// Most of the time, there is a proper managed type, but not for basic collections.
// Since the declaring type is needed for certain operations, we use the one from the target side of the FK
keyDeclaringType = declaringType;
}
if (isReferenceToPrimaryKey) {
fkTarget = collectionDescriptor.getOwnerEntityPersister().getIdentifierMapping();
} else {
fkTarget = declaringType.findAttributeMapping(lhsPropertyName);
}
if (keyType instanceof BasicType) {
assert bootValueMappingKey.getColumnSpan() == 1;
assert fkTarget instanceof BasicValuedModelPart;
final BasicValuedModelPart simpleFkTarget = (BasicValuedModelPart) fkTarget;
final String tableExpression = getTableIdentifierExpression(bootValueMappingKey.getTable(), creationProcess);
final SelectableMapping keySelectableMapping = SelectableMappingImpl.from(tableExpression, bootValueMappingKey.getSelectables().get(0), (JdbcMapping) keyType, dialect, creationProcess.getSqmFunctionRegistry());
attributeMapping.setForeignKeyDescriptor(new SimpleForeignKeyDescriptor(keyDeclaringType, simpleFkTarget, null, keySelectableMapping, simpleFkTarget, isReferenceToPrimaryKey, ((SimpleValue) bootValueMappingKey).isConstrained()));
} else if (fkTarget instanceof EmbeddableValuedModelPart) {
final EmbeddedForeignKeyDescriptor embeddedForeignKeyDescriptor = buildEmbeddableForeignKeyDescriptor((EmbeddableValuedModelPart) fkTarget, bootValueMapping, keyDeclaringType, collectionDescriptor.getAttributeMapping(), false, dialect, creationProcess);
attributeMapping.setForeignKeyDescriptor(embeddedForeignKeyDescriptor);
} else {
throw new NotYetImplementedFor6Exception("Support for " + fkTarget.getClass() + " foreign keys not yet implemented: " + bootValueMapping.getRole());
}
}
use of org.hibernate.metamodel.mapping.EmbeddableValuedModelPart in project hibernate-orm by hibernate.
the class AbstractDomainPath method addSortSpecification.
private void addSortSpecification(EmbeddableValuedModelPart embeddableValuedModelPart, QuerySpec ast, TableGroup tableGroup, String collation, String modelPartName, SortOrder sortOrder, NullPrecedence nullPrecedence, SqlAstCreationState creationState) {
if (embeddableValuedModelPart.getFetchableName().equals(modelPartName) || ELEMENT_TOKEN.equals(modelPartName)) {
embeddableValuedModelPart.forEachSelectable((columnIndex, selection) -> {
addSortSpecification(selection, ast, tableGroup, collation, sortOrder, nullPrecedence, creationState);
});
} else {
ModelPart subPart = embeddableValuedModelPart.findSubPart(modelPartName, null);
assert subPart instanceof BasicValuedModelPart;
addSortSpecification((BasicValuedModelPart) subPart, ast, tableGroup, collation, sortOrder, nullPrecedence, creationState);
}
}
use of org.hibernate.metamodel.mapping.EmbeddableValuedModelPart in project hibernate-orm by hibernate.
the class PluralAttributePath method resolvePathPart.
@Override
public DomainPath resolvePathPart(String name, String identifier, boolean isTerminal, TranslationContext translationContext) {
final ModelPart subPart = pluralAttributeMapping.findSubPart(name, null);
if (subPart != null) {
if (subPart instanceof CollectionPart) {
return new CollectionPartPath(this, (CollectionPart) subPart);
}
if (subPart instanceof EmbeddableValuedModelPart) {
return new DomainPathContinuation(navigablePath.append(name), this, subPart);
}
if (subPart instanceof ToOneAttributeMapping) {
return new FkDomainPathContinuation(navigablePath.append(name), this, (ToOneAttributeMapping) subPart);
}
// leaf case:
final CollectionPartPath elementPath = new CollectionPartPath(this, pluralAttributeMapping.getElementDescriptor());
return (DomainPath) elementPath.resolvePathPart(name, identifier, isTerminal, translationContext);
}
if (pluralAttributeMapping.getElementDescriptor() instanceof EmbeddableValuedModelPart) {
final EmbeddableValuedModelPart elementDescriptor = (EmbeddableValuedModelPart) pluralAttributeMapping.getElementDescriptor();
final ModelPart elementSubPart = elementDescriptor.findSubPart(name, null);
if (elementSubPart != null) {
// create the CollectionSubPath to use as the `lhs` for the element sub-path
final CollectionPartPath elementPath = new CollectionPartPath(this, (CollectionPart) elementDescriptor);
return new DomainPathContinuation(elementPath.getNavigablePath().append(name), this, elementSubPart);
}
}
if (pluralAttributeMapping.getIndexDescriptor() instanceof EmbeddableValuedModelPart) {
final EmbeddableValuedModelPart indexDescriptor = (EmbeddableValuedModelPart) pluralAttributeMapping.getIndexDescriptor();
final ModelPart indexSubPart = indexDescriptor.findSubPart(name, null);
if (indexSubPart != null) {
// create the CollectionSubPath to use as the `lhs` for the element sub-path
final CollectionPartPath indexPath = new CollectionPartPath(this, (CollectionPart) indexDescriptor);
return new DomainPathContinuation(indexPath.getNavigablePath().append(name), this, indexSubPart);
}
}
return null;
}
Aggregations