From f474449e7d949ea0d43cf911cf1b092975125199 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Mon, 21 Mar 2022 14:10:59 -0500 Subject: [PATCH] HHH-15132 - Improvements for NavigablePath Begin breaking down "full path" --- .../internal/EntityCollectionPart.java | 6 +- .../internal/PluralAttributeMappingImpl.java | 2 +- .../internal/ToOneAttributeMapping.java | 30 ++--- .../ordering/ast/FunctionExpression.java | 2 +- .../hql/internal/SemanticQueryBuilder.java | 4 +- .../hql/internal/SqmPathRegistryImpl.java | 2 +- .../ImplicitFetchBuilderEmbeddable.java | 2 +- .../implicit/ImplicitFetchBuilderEntity.java | 2 +- .../sqm/sql/BaseSqmToSqlAstConverter.java | 6 +- .../sqm/tree/domain/AbstractSqmPath.java | 2 +- .../domain/SqmPluralValuedSimplePath.java | 2 +- .../tree/expression/SqmAliasedNodeRef.java | 2 +- .../java/org/hibernate/spi/NavigablePath.java | 51 +++++--- .../hibernate/spi/TreatedNavigablePath.java | 5 - .../AbstractEmbeddableInitializer.java | 14 +-- .../internal/EmbeddableFetchImpl.java | 2 +- .../entity/internal/EntityResultImpl.java | 5 +- .../EntitySelectFetchInitializer.java | 4 +- .../orm/test/spi/path/NavigablePathTests.java | 114 ++++++++++++++++++ 19 files changed, 190 insertions(+), 67 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/spi/path/NavigablePathTests.java diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityCollectionPart.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityCollectionPart.java index bc1d647a85..6b8786fc67 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityCollectionPart.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityCollectionPart.java @@ -667,14 +667,14 @@ public class EntityCollectionPart NavigablePath path = np.getParent(); // Fast path if ( navigablePath.equals( path ) ) { - return targetKeyPropertyNames.contains( np.getUnaliasedLocalName() ) + return targetKeyPropertyNames.contains( np.getLocalName() ) && fkDescriptor.getKeyTable().equals( tableExpression ); } final StringBuilder sb = new StringBuilder( np.getFullPath().length() ); - sb.append( np.getUnaliasedLocalName() ); + sb.append( np.getLocalName() ); while ( path != null && !navigablePath.equals( path ) ) { sb.insert( 0, '.' ); - sb.insert( 0, path.getUnaliasedLocalName() ); + sb.insert( 0, path.getLocalName() ); path = path.getParent(); } return navigablePath.equals( path ) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/PluralAttributeMappingImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/PluralAttributeMappingImpl.java index 9a24be058b..77fb4146f3 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/PluralAttributeMappingImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/PluralAttributeMappingImpl.java @@ -202,7 +202,7 @@ public class PluralAttributeMappingImpl // then we say this is bidirectional, given that this is only invoked for model parts of the collection elements return fkDescriptor.getTargetPart() == modelPart.getForeignKeyDescriptor().getTargetPart(); } - return fetchablePath.getUnaliasedLocalName().endsWith( bidirectionalAttributeName ); + return fetchablePath.getLocalName().endsWith( bidirectionalAttributeName ); } @SuppressWarnings("unused") diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java index 3c2854081a..9b00440460 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java @@ -748,8 +748,8 @@ public class ToOneAttributeMapping private Key key; } */ - if ( parentNavigablePath.getUnaliasedLocalName().equals( ForeignKeyDescriptor.PART_NAME ) - || parentNavigablePath.getUnaliasedLocalName().equals( ForeignKeyDescriptor.TARGET_PART_NAME ) ) { + if ( parentNavigablePath.getLocalName().equals( ForeignKeyDescriptor.PART_NAME ) + || parentNavigablePath.getLocalName().equals( ForeignKeyDescriptor.TARGET_PART_NAME ) ) { // todo (6.0): maybe it's better to have a flag in creation state that marks if we are building a circular fetch domain result already to skip this? return null; } @@ -893,9 +893,9 @@ public class ToOneAttributeMapping parent.getFullPath() = "Mother.biologicalChild" */ final NavigablePath grandparentNavigablePath = parentNavigablePath.getParent(); - if ( parentNavigablePath.getUnaliasedLocalName().equals( CollectionPart.Nature.ELEMENT.getName() ) + if ( parentNavigablePath.getLocalName().equals( CollectionPart.Nature.ELEMENT.getName() ) && grandparentNavigablePath != null - && grandparentNavigablePath.getUnaliasedLocalName().equals( bidirectionalAttributeName ) ) { + && grandparentNavigablePath.getLocalName().equals( bidirectionalAttributeName ) ) { final NavigablePath parentPath = grandparentNavigablePath.getParent(); // This can be null for a collection loader if ( parentPath == null ) { @@ -915,13 +915,13 @@ public class ToOneAttributeMapping } // If we have a parent, we ensure that the parent is the same as the attribute name else { - return parentPath.getUnaliasedLocalName().equals( navigableRole.getLocalName() ); + return parentPath.getLocalName().equals( navigableRole.getLocalName() ); } } } return false; } - return parentNavigablePath.getUnaliasedLocalName().equals( bidirectionalAttributeName ); + return parentNavigablePath.getLocalName().equals( bidirectionalAttributeName ); } public String getBidirectionalAttributeName(){ @@ -944,7 +944,7 @@ public class ToOneAttributeMapping referencedNavigablePath = parentNavigablePath; hasBidirectionalFetchParent = true; } - else if ( CollectionPart.Nature.fromNameExact( parentNavigablePath.getUnaliasedLocalName() ) != null ) { + else if ( CollectionPart.Nature.fromNameExact( parentNavigablePath.getLocalName() ) != null ) { referencedNavigablePath = parentNavigablePath.getParent().getParent(); hasBidirectionalFetchParent = fetchParent instanceof Fetch && ( (Fetch) fetchParent ).getFetchParent() instanceof Fetch; @@ -1007,7 +1007,7 @@ public class ToOneAttributeMapping // So we create a delayed fetch, as we are sure to find the entity in the PC final FromClauseAccess fromClauseAccess = creationState.getSqlAstCreationState().getFromClauseAccess(); final NavigablePath realParent; - if ( CollectionPart.Nature.fromNameExact( parentNavigablePath.getUnaliasedLocalName() ) != null ) { + if ( CollectionPart.Nature.fromNameExact( parentNavigablePath.getLocalName() ) != null ) { realParent = parentNavigablePath.getParent(); } else { @@ -1386,7 +1386,7 @@ public class ToOneAttributeMapping break; } } - if ( CollectionPart.Nature.ELEMENT.getName().equals( parentTableGroup.getNavigablePath().getUnaliasedLocalName() ) ) { + if ( CollectionPart.Nature.ELEMENT.getName().equals( parentTableGroup.getNavigablePath().getLocalName() ) ) { final PluralTableGroup pluralTableGroup = (PluralTableGroup) fromClauseAccess.findTableGroup( parentTableGroup.getNavigablePath().getParent() ); @@ -1420,14 +1420,14 @@ public class ToOneAttributeMapping NavigablePath path = np.getParent(); // Fast path if ( navigablePath.equals( path ) ) { - return targetKeyPropertyNames.contains( np.getUnaliasedLocalName() ) + return targetKeyPropertyNames.contains( np.getLocalName() ) && identifyingColumnsTableExpression.equals( tableExpression ); } final StringBuilder sb = new StringBuilder( np.getFullPath().length() ); - sb.append( np.getUnaliasedLocalName() ); + sb.append( np.getLocalName() ); while ( path != null && !navigablePath.equals( path ) ) { sb.insert( 0, '.' ); - sb.insert( 0, path.getUnaliasedLocalName() ); + sb.insert( 0, path.getLocalName() ); path = path.getParent(); } return navigablePath.equals( path ) @@ -1542,14 +1542,14 @@ public class ToOneAttributeMapping NavigablePath path = np.getParent(); // Fast path if ( navigablePath.equals( path ) ) { - return targetKeyPropertyNames.contains( np.getUnaliasedLocalName() ) + return targetKeyPropertyNames.contains( np.getLocalName() ) && identifyingColumnsTableExpression.equals( tableExpression ); } final StringBuilder sb = new StringBuilder( np.getFullPath().length() ); - sb.append( np.getUnaliasedLocalName() ); + sb.append( np.getLocalName() ); while ( path != null && !navigablePath.equals( path ) ) { sb.insert( 0, '.' ); - sb.insert( 0, path.getUnaliasedLocalName() ); + sb.insert( 0, path.getLocalName() ); path = path.getParent(); } return navigablePath.equals( path ) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ordering/ast/FunctionExpression.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ordering/ast/FunctionExpression.java index fcafa872ce..08e509d102 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ordering/ast/FunctionExpression.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ordering/ast/FunctionExpression.java @@ -66,7 +66,7 @@ public class FunctionExpression implements OrderingExpression, FunctionRendering final OrderingExpression orderingExpression = arguments.get( i ); final String subModelPartName; if ( orderingExpression instanceof DomainPath ) { - final String partName = ( (DomainPath) orderingExpression ).getNavigablePath().getUnaliasedLocalName(); + final String partName = ( (DomainPath) orderingExpression ).getNavigablePath().getLocalName(); if ( CollectionPart.Nature.ELEMENT.getName().equals( partName ) ) { subModelPartName = AbstractDomainPath.ELEMENT_TOKEN; } diff --git a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java index 6e4c2b42ce..1d5e70e769 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java @@ -4013,7 +4013,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implem SqmPath lhs = pluralAttributePath.getLhs(); final List implicitJoinPaths = new ArrayList<>(); while ( !( lhs instanceof AbstractSqmFrom ) ) { - implicitJoinPaths.add( lhs.getNavigablePath().getUnaliasedLocalName() ); + implicitJoinPaths.add( lhs.getNavigablePath().getLocalName() ); lhs = lhs.getLhs(); } final AbstractSqmFrom correlationBase = (AbstractSqmFrom) lhs; @@ -4022,7 +4022,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implem for ( int i = implicitJoinPaths.size() - 1; i >= 0; i-- ) { joinBase = joinBase.join( implicitJoinPaths.get( i ) ); } - final SqmAttributeJoin collectionJoin = joinBase.join( pluralAttributePath.getNavigablePath().getUnaliasedLocalName() ); + final SqmAttributeJoin collectionJoin = joinBase.join( pluralAttributePath.getNavigablePath().getLocalName() ); fromClause.addRoot( correlation.getCorrelatedRoot() ); if ( collectionReferenceCtx == null ) { final SqmLiteral literal = new SqmLiteral<>( diff --git a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SqmPathRegistryImpl.java b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SqmPathRegistryImpl.java index 5171d83434..de48246dee 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SqmPathRegistryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SqmPathRegistryImpl.java @@ -240,7 +240,7 @@ public class SqmPathRegistryImpl implements SqmPathRegistry { return (X) existing; } - final SqmFrom sqmFrom = resolveFrom( path.getLhs() ).join( path.getNavigablePath().getUnaliasedLocalName() ); + final SqmFrom sqmFrom = resolveFrom( path.getLhs() ).join( path.getNavigablePath().getLocalName() ); register( sqmFrom ); //noinspection unchecked return (X) sqmFrom; diff --git a/hibernate-core/src/main/java/org/hibernate/query/results/implicit/ImplicitFetchBuilderEmbeddable.java b/hibernate-core/src/main/java/org/hibernate/query/results/implicit/ImplicitFetchBuilderEmbeddable.java index 9ef0cdbf02..6bb65705d6 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/results/implicit/ImplicitFetchBuilderEmbeddable.java +++ b/hibernate-core/src/main/java/org/hibernate/query/results/implicit/ImplicitFetchBuilderEmbeddable.java @@ -171,6 +171,6 @@ public class ImplicitFetchBuilderEmbeddable implements ImplicitFetchBuilder { @Override public void visitFetchBuilders(BiConsumer consumer) { - fetchBuilders.forEach( (k, v) -> consumer.accept( k.getUnaliasedLocalName(), v ) ); + fetchBuilders.forEach( (k, v) -> consumer.accept( k.getLocalName(), v ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/results/implicit/ImplicitFetchBuilderEntity.java b/hibernate-core/src/main/java/org/hibernate/query/results/implicit/ImplicitFetchBuilderEntity.java index f95c8e8e76..30963e6995 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/results/implicit/ImplicitFetchBuilderEntity.java +++ b/hibernate-core/src/main/java/org/hibernate/query/results/implicit/ImplicitFetchBuilderEntity.java @@ -151,7 +151,7 @@ public class ImplicitFetchBuilderEntity implements ImplicitFetchBuilder { @Override public void visitFetchBuilders(BiConsumer consumer) { - fetchBuilders.forEach( (k, v) -> consumer.accept( k.getUnaliasedLocalName(), v ) ); + fetchBuilders.forEach( (k, v) -> consumer.accept( k.getLocalName(), v ) ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java index 2406b665f7..badb3d9d88 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java @@ -2983,7 +2983,7 @@ public abstract class BaseSqmToSqlAstConverter extends Base prepareReusablePath( path, () -> null ); final NavigablePath navigablePath; - if ( CollectionPart.Nature.fromNameExact( path.getNavigablePath().getUnaliasedLocalName() ) != null ) { + if ( CollectionPart.Nature.fromNameExact( path.getNavigablePath().getLocalName() ) != null ) { navigablePath = path.getLhs().getLhs().getNavigablePath(); } else if ( path instanceof SqmTreatedRoot ) { @@ -3648,7 +3648,7 @@ public abstract class BaseSqmToSqlAstConverter extends Base assert parentTableGroup != null; final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) parentTableGroup.getModelPart().findSubPart( - pluralPath.getNavigablePath().getUnaliasedLocalName(), + pluralPath.getNavigablePath().getLocalName(), null ); assert pluralAttributeMapping != null; @@ -5344,7 +5344,7 @@ public abstract class BaseSqmToSqlAstConverter extends Base path.getLhs().getNavigablePath() ); final NavigablePath navigablePath = parentTableGroup.getNavigablePath().append( - path.getNavigablePath().getUnaliasedLocalName(), + path.getNavigablePath().getLocalName(), Long.toString( System.nanoTime() ) ); final TableGroup tableGroup = new SyntheticVirtualTableGroup( diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmPath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmPath.java index c7647135d8..c7117e8564 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmPath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmPath.java @@ -103,7 +103,7 @@ public abstract class AbstractSqmPath extends AbstractSqmExpression implem reusablePaths = new HashMap<>(); } - final String relativeName = path.getNavigablePath().getUnaliasedLocalName(); + final String relativeName = path.getNavigablePath().getLocalName(); final SqmPath previous = reusablePaths.put( relativeName, path ); if ( previous != null && previous != path ) { diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPluralValuedSimplePath.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPluralValuedSimplePath.java index 2c1c1eb54f..88f26e0580 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPluralValuedSimplePath.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPluralValuedSimplePath.java @@ -108,7 +108,7 @@ public class SqmPluralValuedSimplePath extends AbstractSqmSimplePath { final SqmPathRegistry pathRegistry = creationState.getCurrentProcessingState().getPathRegistry(); final String alias = selector.toHqlString(); final NavigablePath navigablePath = getNavigablePath().getParent().append( - getNavigablePath().getUnaliasedLocalName(), + getNavigablePath().getLocalName(), alias ).append( CollectionPart.Nature.ELEMENT.getName() ); final SqmFrom indexedPath = pathRegistry.findFromByPath( navigablePath ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmAliasedNodeRef.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmAliasedNodeRef.java index 94ceb8a900..1ffabce6d5 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmAliasedNodeRef.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/expression/SqmAliasedNodeRef.java @@ -77,7 +77,7 @@ public class SqmAliasedNodeRef extends AbstractSqmExpression { sb.append( position ); } else { - sb.append( navigablePath.getUnaliasedLocalName() ); + sb.append( navigablePath.getLocalName() ); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/spi/NavigablePath.java b/hibernate-core/src/main/java/org/hibernate/spi/NavigablePath.java index 8757a9c472..9a5d102483 100644 --- a/hibernate-core/src/main/java/org/hibernate/spi/NavigablePath.java +++ b/hibernate-core/src/main/java/org/hibernate/spi/NavigablePath.java @@ -23,23 +23,28 @@ public class NavigablePath implements DotIdentifierSequence, Serializable { public static final String IDENTIFIER_MAPPER_PROPERTY = "_identifierMapper"; private final NavigablePath parent; - private final String fullPath; - private final String unaliasedLocalName; + private final String localName; + private final String alias; + private final String identifierForTableGroup; + private final String fullPath; + public NavigablePath(NavigablePath parent, String navigableName) { this.parent = parent; + this.alias = null; // the _identifierMapper is a "hidden property" on entities with composite keys. // concatenating it will prevent the path from correctly being used to look up // various things such as criteria paths and fetch profile association paths if ( IDENTIFIER_MAPPER_PROPERTY.equals( navigableName ) ) { - this.fullPath = parent != null ? parent.getFullPath() : ""; - this.unaliasedLocalName = ""; + this.localName = ""; this.identifierForTableGroup = parent != null ? parent.getIdentifierForTableGroup() : ""; + + this.fullPath = parent != null ? parent.getFullPath() : ""; } else { - this.unaliasedLocalName = navigableName; + this.localName = navigableName; if ( parent != null ) { final String parentFullPath = parent.getFullPath(); this.fullPath = StringHelper.isEmpty( parentFullPath ) @@ -51,7 +56,7 @@ public class NavigablePath implements DotIdentifierSequence, Serializable { } else { this.fullPath = navigableName; - identifierForTableGroup = navigableName; + this.identifierForTableGroup = navigableName; } } } @@ -62,28 +67,32 @@ public class NavigablePath implements DotIdentifierSequence, Serializable { public NavigablePath(String rootName, String alias) { this.parent = null; + this.alias = StringHelper.nullIfEmpty( alias ); + this.localName = rootName; + this.identifierForTableGroup = rootName; + this.fullPath = alias == null ? rootName : rootName + "(" + alias + ")"; - this.unaliasedLocalName = StringHelper.unqualify( rootName ); - identifierForTableGroup = rootName; } public NavigablePath(NavigablePath parent, String property, String alias) { - String navigableName = alias == null + alias = StringHelper.nullIfEmpty( alias ); + final String navigableName = alias == null ? property : property + '(' + alias + ')'; this.parent = parent; + this.alias = alias; // the _identifierMapper is a "hidden property" on entities with composite keys. // concatenating it will prevent the path from correctly being used to look up // various things such as criteria paths and fetch profile association paths if ( IDENTIFIER_MAPPER_PROPERTY.equals( navigableName ) ) { this.fullPath = parent != null ? parent.getFullPath() : ""; - this.unaliasedLocalName = ""; + this.localName = ""; identifierForTableGroup = parent != null ? parent.getFullPath() : ""; } else { - this.unaliasedLocalName = property; + this.localName = property; if ( parent != null ) { final String parentFullPath = parent.getFullPath(); this.fullPath = StringHelper.isEmpty( parentFullPath ) @@ -107,11 +116,12 @@ public class NavigablePath implements DotIdentifierSequence, Serializable { public NavigablePath( NavigablePath parent, String fullPath, - String unaliasedLocalName, + String localName, String identifierForTableGroup) { this.parent = parent; + this.alias = null; this.fullPath = fullPath; - this.unaliasedLocalName = unaliasedLocalName; + this.localName = localName; this.identifierForTableGroup = identifierForTableGroup; } @@ -140,24 +150,29 @@ public class NavigablePath implements DotIdentifierSequence, Serializable { } public String getLocalName() { - return parent == null ? fullPath : StringHelper.unqualify( fullPath ); + return localName; } - public String getUnaliasedLocalName() { - return unaliasedLocalName; + public String getAlias() { + return alias; } - public String getFullPath() { - return fullPath; + public boolean isAliased() { + return alias != null; } public String getIdentifierForTableGroup() { + // todo (6.0) : is this `if` really needed? seems this is already handled in constructors if ( parent == null ) { return fullPath; } return identifierForTableGroup; } + public String getFullPath() { + return fullPath; + } + public boolean isParent(NavigablePath navigablePath) { while ( navigablePath != null ) { if ( this.equals( navigablePath.getParent() ) ) { diff --git a/hibernate-core/src/main/java/org/hibernate/spi/TreatedNavigablePath.java b/hibernate-core/src/main/java/org/hibernate/spi/TreatedNavigablePath.java index 7c6ed94104..09c575b006 100644 --- a/hibernate-core/src/main/java/org/hibernate/spi/TreatedNavigablePath.java +++ b/hibernate-core/src/main/java/org/hibernate/spi/TreatedNavigablePath.java @@ -41,11 +41,6 @@ public class TreatedNavigablePath extends NavigablePath { return new TreatedNavigablePath( getRealParent(), entityName, alias ); } - @Override - public String getLocalName() { - return getUnaliasedLocalName(); - } - @Override public int hashCode() { return getFullPath().hashCode(); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/AbstractEmbeddableInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/AbstractEmbeddableInitializer.java index e14add6c4e..4036e6e3e5 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/AbstractEmbeddableInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/AbstractEmbeddableInitializer.java @@ -108,9 +108,9 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA ); // We never want to create empty composites for the FK target or PK, otherwise collections would break - createEmptyCompositesEnabled = !ForeignKeyDescriptor.PART_NAME.equals( navigablePath.getUnaliasedLocalName() ) - && !ForeignKeyDescriptor.TARGET_PART_NAME.equals( navigablePath.getUnaliasedLocalName() ) - && !EntityIdentifierMapping.ROLE_LOCAL_NAME.equals( navigablePath.getUnaliasedLocalName() ) + createEmptyCompositesEnabled = !ForeignKeyDescriptor.PART_NAME.equals( navigablePath.getLocalName() ) + && !ForeignKeyDescriptor.TARGET_PART_NAME.equals( navigablePath.getLocalName() ) + && !EntityIdentifierMapping.ROLE_LOCAL_NAME.equals( navigablePath.getLocalName() ) && embeddableTypeDescriptor.isCreateEmptyCompositesEnabled(); sessionFactory = creationState.getSqlAstCreationContext().getSessionFactory(); @@ -232,8 +232,8 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA // so we can't use the fetch parent access in that case. if ( fetchParentAccess != null && embedded instanceof VirtualModelPart && !EntityIdentifierMapping.ROLE_LOCAL_NAME.equals( embedded.getFetchableName() ) - && !ForeignKeyDescriptor.PART_NAME.equals( navigablePath.getUnaliasedLocalName() ) - && !ForeignKeyDescriptor.TARGET_PART_NAME.equals( navigablePath.getUnaliasedLocalName() ) ) { + && !ForeignKeyDescriptor.PART_NAME.equals( navigablePath.getLocalName() ) + && !ForeignKeyDescriptor.TARGET_PART_NAME.equals( navigablePath.getLocalName() ) ) { fetchParentAccess.resolveInstance( processingState ); compositeInstance = fetchParentAccess.getInitializedInstance(); } @@ -255,8 +255,8 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA private void extractRowState(RowProcessingState processingState) { stateAllNull = true; - final boolean isKey = ForeignKeyDescriptor.PART_NAME.equals( navigablePath.getUnaliasedLocalName() ) - || ForeignKeyDescriptor.TARGET_PART_NAME.equals( navigablePath.getUnaliasedLocalName() ) + final boolean isKey = ForeignKeyDescriptor.PART_NAME.equals( navigablePath.getLocalName() ) + || ForeignKeyDescriptor.TARGET_PART_NAME.equals( navigablePath.getLocalName() ) || EntityIdentifierMapping.ROLE_LOCAL_NAME.equals( embedded.getFetchableName() ); for ( int i = 0; i < assemblers.size(); i++ ) { final DomainResultAssembler assembler = assemblers.get( i ); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java index 909f34676e..022f97a124 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java @@ -112,7 +112,7 @@ public class EmbeddableFetchImpl extends AbstractFetchParent implements Embeddab for ( TableGroupJoin tableGroupJoin : tableGroup.getTableGroupJoins() ) { final NavigablePath navigablePath = tableGroupJoin.getNavigablePath(); if ( tableGroupJoin.getJoinedGroup().isFetched() - && fetchable.getFetchableName().equals( navigablePath.getUnaliasedLocalName() ) + && fetchable.getFetchableName().equals( navigablePath.getLocalName() ) && tableGroupJoin.getJoinedGroup().getModelPart() == fetchable ) { return navigablePath; } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityResultImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityResultImpl.java index 83622b4e89..2f92f25da0 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityResultImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityResultImpl.java @@ -56,12 +56,11 @@ public class EntityResultImpl extends AbstractEntityResultGraphNode implements E @Override public NavigablePath resolveNavigablePath(Fetchable fetchable) { - if ( fetchable instanceof TableGroupProducer && - !getNavigablePath().getUnaliasedLocalName().equals( getNavigablePath().getLocalName() ) ) { + if ( fetchable instanceof TableGroupProducer && getNavigablePath().isAliased() ) { for ( TableGroupJoin tableGroupJoin : tableGroup.getTableGroupJoins() ) { final NavigablePath navigablePath = tableGroupJoin.getNavigablePath(); if ( tableGroupJoin.getJoinedGroup().isFetched() - && fetchable.getFetchableName().equals( navigablePath.getUnaliasedLocalName() ) + && fetchable.getFetchableName().equals( navigablePath.getLocalName() ) && tableGroupJoin.getJoinedGroup().getModelPart() == fetchable ) { return navigablePath; } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializer.java index 2a156d5075..62aab9cd2f 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializer.java @@ -88,8 +88,8 @@ public class EntitySelectFetchInitializer extends AbstractFetchParentAccess impl NavigablePath np = navigablePath.getParent(); while ( np != null ) { if ( np instanceof EntityIdentifierNavigablePath - || ForeignKeyDescriptor.PART_NAME.equals( np.getUnaliasedLocalName() ) - || ForeignKeyDescriptor.TARGET_PART_NAME.equals( np.getUnaliasedLocalName() )) { + || ForeignKeyDescriptor.PART_NAME.equals( np.getLocalName() ) + || ForeignKeyDescriptor.TARGET_PART_NAME.equals( np.getLocalName() )) { initializeInstance( rowProcessingState ); return; } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/spi/path/NavigablePathTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/spi/path/NavigablePathTests.java new file mode 100644 index 0000000000..6574b2d39a --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/spi/path/NavigablePathTests.java @@ -0,0 +1,114 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.orm.test.spi.path; + +import org.hibernate.metamodel.mapping.EntityIdentifierMapping; +import org.hibernate.spi.EntityIdentifierNavigablePath; +import org.hibernate.spi.NavigablePath; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Steve Ebersole + */ +public class NavigablePathTests { + @Test + public void testRoots() { + final NavigablePath root = new NavigablePath( "org.hibernate.Root", "r" ); + assertThat( root.equals( root ) ).isTrue(); + assertThat( root.getFullPath() ).isEqualTo( "org.hibernate.Root(r)" ); + assertThat( root.getLocalName() ).isEqualTo( "org.hibernate.Root" ); + assertThat( root.isAliased() ).isTrue(); + assertThat( root.getAlias() ).isEqualTo( "r" ); + + final NavigablePath root2 = new NavigablePath( "org.hibernate.Root", "r" ); + assertThat( root.equals( root2 ) ).isTrue(); + } + + @Test + public void testSubPaths() { + final NavigablePath root = new NavigablePath( "org.hibernate.Root", "r" ); + + final NavigablePath name1 = root.append( "name" ); + final NavigablePath name2 = root.append( "name" ); + + assertThat( name1.equals( name2 ) ).isTrue(); + + final NavigablePath id = root.append( "id" ); + + assertThat( name1.equals( root ) ).isFalse(); + assertThat( id.equals( root ) ).isFalse(); + } + + @Test + public void testParallelSubPaths() { + final NavigablePath root1 = new NavigablePath( "org.hibernate.Root", "r" ); + final NavigablePath root2 = new NavigablePath( "org.hibernate.Root", "r" ); + + final NavigablePath name1 = root1.append( "name" ); + final NavigablePath name2 = root2.append( "name" ); + + assertThat( name1.equals( name2 ) ).isTrue(); + } + + @Test + public void testNestedPaths() { + final NavigablePath root = new NavigablePath( "org.hibernate.Root", "r" ); + + final NavigablePath comp1 = root.append( "comp" ); + final NavigablePath comp2 = root.append( "comp" ); + + final NavigablePath comp1Name = comp1.append( "name" ); + final NavigablePath comp2Name = comp2.append( "name" ); + + assertThat( comp1Name.equals( comp2Name ) ).isTrue(); + } + + @Test + public void testDivergentNestedPaths() { + final NavigablePath root = new NavigablePath( "org.hibernate.Root", "r" ); + + final NavigablePath comp = root.append( "comp" ); + final NavigablePath other = root.append( "other" ); + + final NavigablePath compName = comp.append( "name" ); + final NavigablePath otherName = other.append( "name" ); + + assertThat( compName.equals( otherName ) ).isFalse(); + } + + @Test + public void testStringification() { + final String rootStr = "org.hibernate.Root"; + final String aliasedRootStr = "org.hibernate.Root(r)"; + final String nameStr = "name"; + final String namePathStr = aliasedRootStr + "." + nameStr; + + final NavigablePath root = new NavigablePath( rootStr, "r" ); + + final NavigablePath name = root.append( "name" ); + assertThat( name.getLocalName() ).isEqualTo( nameStr ); + assertThat( name.getFullPath() ).isEqualTo( namePathStr ); + } + + @Test + public void testIdentifierPaths() { + final String rootStr = "org.hibernate.Root"; + final String aliasedRootStr = "org.hibernate.Root(r)"; + + final String pkStr = "pk"; + final String pkFullPathStr = aliasedRootStr + "." + EntityIdentifierMapping.ROLE_LOCAL_NAME; + + final NavigablePath root = new NavigablePath( rootStr, "r" ); + + final NavigablePath idPath = new EntityIdentifierNavigablePath( root, pkStr ); + assertThat( idPath.getLocalName() ).isEqualTo( EntityIdentifierMapping.ROLE_LOCAL_NAME ); + assertThat( idPath.getFullPath() ).isEqualTo( pkFullPathStr ); + } +}