From 6299ceb61d9e08b56f9877e576237babff676f34 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sun, 2 Jul 2023 15:03:57 +0200 Subject: [PATCH] fix up lots of errors in generic typing related to DomainTypes... ...and reduce coupling to JpaMetamodel. This is useful for tools like Query Validator which need to instantiate these metamodel objects in a "mocked" environment. It will also make it possible for the Metamodel Generator to generate static references to these metamodel objects. --- .../query/HbmResultSetMappingDescriptor.java | 2 +- .../query/SqlResultSetMappingDescriptor.java | 2 +- .../graph/internal/AttributeNodeImpl.java | 23 +- .../internal/parse/PathQualifierType.java | 15 +- .../ast/internal/AbstractNaturalIdLoader.java | 3 +- .../AbstractCompositeIdentifierMapping.java | 3 +- .../mapping/EntityDiscriminatorMapping.java | 10 +- .../mapping/EntityIdentifierMapping.java | 10 +- .../metamodel/mapping/MappingModelHelper.java | 158 +++++++------- .../AbstractDiscriminatorMapping.java | 2 +- .../AbstractEntityCollectionPart.java | 10 +- .../internal/AnyDiscriminatorPart.java | 3 +- .../BasicEntityIdentifierMappingImpl.java | 2 +- ...CaseStatementDiscriminatorMappingImpl.java | 2 +- .../mapping/internal/IdClassEmbeddable.java | 4 +- ...InverseNonAggregatedIdentifierMapping.java | 2 +- .../NonAggregatedIdentifierMappingImpl.java | 2 +- .../SingleAttributeIdentifierMapping.java | 2 +- .../internal/ToOneAttributeMapping.java | 26 +-- .../model/domain/AbstractDomainType.java | 11 +- .../domain/AbstractIdentifiableType.java | 51 +++-- .../model/domain/AbstractManagedType.java | 196 ++++++------------ .../model/domain/IdentifiableDomainType.java | 2 +- .../model/domain/ManagedDomainType.java | 33 ++- .../internal/AbstractPluralAttribute.java | 9 + .../internal/DiscriminatorSqmPathSource.java | 2 +- .../domain/internal/DomainModelHelper.java | 81 ++++++-- .../domain/internal/EmbeddableTypeImpl.java | 11 +- .../domain/internal/EntitySqmPathSource.java | 9 +- .../model/domain/internal/EntityTypeImpl.java | 111 ++++++---- .../domain/internal/JpaMetamodelImpl.java | 4 +- .../domain/internal/ListAttributeImpl.java | 15 ++ .../domain/internal/MapAttributeImpl.java | 15 ++ .../internal/MappedSuperclassTypeImpl.java | 34 +-- .../internal/SingularAttributeImpl.java | 6 + .../metamodel/model/domain/package-info.java | 3 + .../entity/AbstractEntityPersister.java | 6 +- .../internal/EntityDomainResultBuilder.java | 2 +- .../AnonymousTupleEntityValuedModelPart.java | 2 +- .../query/derived/AnonymousTupleType.java | 8 +- .../internal/QualifiedJoinPathConsumer.java | 149 +++++++------ .../hql/internal/SqmPathRegistryImpl.java | 7 +- .../query/results/ResultsHelper.java | 5 +- .../CompleteResultBuilderEntityJpa.java | 2 +- .../CompleteResultBuilderEntityStandard.java | 2 +- .../hibernate/query/sqm/SqmPathSource.java | 51 ++++- .../query/sqm/internal/QuerySqmImpl.java | 2 +- .../sqm/sql/BaseSqmToSqlAstConverter.java | 2 +- .../sqm/tree/domain/AbstractSqmFrom.java | 15 +- .../sqm/tree/domain/AbstractSqmPath.java | 11 +- .../domain/SqmPolymorphicRootDescriptor.java | 132 ++++++------ .../spi/EntityIdentifierNavigablePath.java | 6 +- .../graph/DomainResultCreationState.java | 7 +- .../AbstractEmbeddableInitializer.java | 2 +- .../internal/EntityDelayedResultImpl.java | 3 +- .../simple/dynamic/SimpleDynamicHbmTests.java | 2 +- .../hbm/simple/pojo/SimpleHbmTests.java | 2 +- .../test/query/hql/AttributePathTests.java | 2 +- .../orm/test/spi/path/NavigablePathTests.java | 4 +- 59 files changed, 681 insertions(+), 617 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/boot/query/HbmResultSetMappingDescriptor.java b/hibernate-core/src/main/java/org/hibernate/boot/query/HbmResultSetMappingDescriptor.java index d5a8e9a845..75f9f638a0 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/query/HbmResultSetMappingDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/query/HbmResultSetMappingDescriptor.java @@ -402,7 +402,7 @@ public class HbmResultSetMappingDescriptor implements NamedResultSetMappingDescr } discriminatorMemento = new FetchMementoBasicStandard( - entityPath.append( EntityDiscriminatorMapping.ROLE_NAME ), + entityPath.append( EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME ), entityDescriptor.getDiscriminatorMapping(), discriminatorColumnAlias ); diff --git a/hibernate-core/src/main/java/org/hibernate/boot/query/SqlResultSetMappingDescriptor.java b/hibernate-core/src/main/java/org/hibernate/boot/query/SqlResultSetMappingDescriptor.java index 527a2a8da3..ea6a554626 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/query/SqlResultSetMappingDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/query/SqlResultSetMappingDescriptor.java @@ -285,7 +285,7 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr } return new FetchMementoBasicStandard( - entityPath.append( EntityDiscriminatorMapping.ROLE_NAME ), + entityPath.append( EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME ), discriminatorMapping, discriminatorColumn ); diff --git a/hibernate-core/src/main/java/org/hibernate/graph/internal/AttributeNodeImpl.java b/hibernate-core/src/main/java/org/hibernate/graph/internal/AttributeNodeImpl.java index d121464889..36f4b5aa2c 100644 --- a/hibernate-core/src/main/java/org/hibernate/graph/internal/AttributeNodeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/graph/internal/AttributeNodeImpl.java @@ -21,12 +21,14 @@ import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.PersistentAttribute; import org.hibernate.metamodel.model.domain.SimpleDomainType; +import org.hibernate.metamodel.model.domain.internal.DomainModelHelper; import org.jboss.logging.Logger; import static java.util.Collections.emptyMap; +import static org.hibernate.metamodel.model.domain.internal.DomainModelHelper.findSubType; /** - * Hibernate implementation of the JPA AttributeNode contract + * Implementation of {@link jakarta.persistence.AttributeNode}. * * @author Steve Ebersole */ @@ -94,7 +96,7 @@ public class AttributeNodeImpl private SubGraphImplementor internalMakeSubgraph(ManagedDomainType type) { assert type != null; log.debugf( "Making sub-graph : ( (%s) %s )", type.getTypeName(), getAttributeName() ); - final SubGraphImplementor subGraph = type.makeSubGraph(); + final SubGraphImplementor subGraph = DomainModelHelper.makeSubGraph( type, type.getBindableJavaType() ); internalAddSubGraph( subGraph ); return subGraph; } @@ -122,7 +124,7 @@ public class AttributeNodeImpl private SubGraphImplementor internalMakeSubgraph(Class subType) { verifyMutability(); final ManagedDomainType managedType = valueGraphTypeAsManaged(); - return internalMakeSubgraph( managedType.findSubType( subType == null ? managedType.getJavaType() : subType ) ); + return internalMakeSubgraph( findSubType( managedType, subType == null ? managedType.getJavaType() : subType ) ); } protected void internalAddSubGraph(SubGraphImplementor subGraph) { @@ -164,8 +166,9 @@ public class AttributeNodeImpl } private SubGraphImplementor internalMakeKeySubgraph(ManagedDomainType type) { + assert type != null; log.debugf( "Making key sub-graph : ( (%s) %s )", type.getTypeName(), getAttributeName() ); - final SubGraphImplementor subGraph = type.makeSubGraph(); + final SubGraphImplementor subGraph = DomainModelHelper.makeSubGraph( type, type.getBindableJavaType() ); internalAddKeySubGraph( subGraph ); return subGraph; } @@ -173,9 +176,7 @@ public class AttributeNodeImpl private SubGraphImplementor internalMakeKeySubgraph(Class type) { verifyMutability(); final ManagedDomainType managedType = keyGraphTypeAsManaged(); - final ManagedDomainType subType = type == null ? managedType : managedType.findSubType( type ); - subType.getJavaType(); - return internalMakeKeySubgraph( subType ); + return internalMakeKeySubgraph( type == null ? managedType : findSubType( managedType, type ) ); } protected void internalAddKeySubGraph(SubGraph subGraph) { @@ -231,7 +232,7 @@ public class AttributeNodeImpl } else { return nodeMap.entrySet().stream() - .map(entry -> Map.entry(entry.getKey(), entry.getValue().makeCopy( mutable ))) + .map(entry -> Map.entry( entry.getKey(), entry.getValue().makeCopy( mutable ) )) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } } @@ -240,9 +241,10 @@ public class AttributeNodeImpl public void merge(AttributeNodeImplementor attributeNode) { attributeNode.visitSubGraphs( (incomingSubType, incomingGraph) -> { - SubGraphImplementor existing = null; + SubGraphImplementor existing; if ( subGraphMap == null ) { subGraphMap = new HashMap<>(); + existing = null; } else { existing = subGraphMap.get( incomingSubType ); @@ -259,9 +261,10 @@ public class AttributeNodeImpl attributeNode.visitKeySubGraphs( (incomingSubType, incomingGraph) -> { - SubGraphImplementor existing = null; + SubGraphImplementor existing; if ( keySubGraphMap == null ) { keySubGraphMap = new HashMap<>(); + existing = null; } else { existing = keySubGraphMap.get( incomingSubType ); diff --git a/hibernate-core/src/main/java/org/hibernate/graph/internal/parse/PathQualifierType.java b/hibernate-core/src/main/java/org/hibernate/graph/internal/parse/PathQualifierType.java index 79b5a9be0a..e7f34d5e8c 100644 --- a/hibernate-core/src/main/java/org/hibernate/graph/internal/parse/PathQualifierType.java +++ b/hibernate-core/src/main/java/org/hibernate/graph/internal/parse/PathQualifierType.java @@ -8,8 +8,10 @@ package org.hibernate.graph.internal.parse; import org.hibernate.graph.CannotContainSubGraphException; import org.hibernate.metamodel.model.domain.DomainType; -import org.hibernate.metamodel.model.domain.SimpleDomainType; import org.hibernate.metamodel.model.domain.ManagedDomainType; +import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; + +import static org.hibernate.metamodel.model.domain.internal.DomainModelHelper.resolveSubType; /** * @author Steve Ebersole @@ -21,7 +23,8 @@ public enum PathQualifierType { attributeNode.makeKeySubGraph( resolveSubTypeManagedType( attributeNode.getAttributeDescriptor().getKeyGraphType(), - subTypeName + subTypeName, + sessionFactory.getJpaMetamodel() ) ) ), @@ -30,14 +33,16 @@ public enum PathQualifierType { attributeNode.makeSubGraph( resolveSubTypeManagedType( attributeNode.getAttributeDescriptor().getValueGraphType(), - subTypeName + subTypeName, + sessionFactory.getJpaMetamodel() ) ) ); private static ManagedDomainType resolveSubTypeManagedType( DomainType graphType, - String subTypeName) { + String subTypeName, + JpaMetamodelImplementor metamodel) { if ( !( graphType instanceof ManagedDomainType ) ) { throw new CannotContainSubGraphException( "The given type [" + graphType + "] is not a ManagedType" ); } @@ -45,7 +50,7 @@ public enum PathQualifierType { ManagedDomainType managedType = (ManagedDomainType) graphType; if ( subTypeName != null ) { - managedType = managedType.findSubType( subTypeName ); + managedType = resolveSubType( managedType, subTypeName, metamodel ); } return managedType; } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractNaturalIdLoader.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractNaturalIdLoader.java index c7c04ced2f..50f48beb95 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractNaturalIdLoader.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractNaturalIdLoader.java @@ -6,7 +6,6 @@ */ package org.hibernate.loader.ast.internal; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; @@ -267,7 +266,7 @@ public abstract class AbstractNaturalIdLoader implements NaturalIdLoader { naturalIdMapping().normalizeInput( naturalIdValue ), NaturalIdLoadOptions.NONE, (tableGroup, creationState) -> entityDescriptor.getIdentifierMapping().createDomainResult( - tableGroup.getNavigablePath().append( EntityIdentifierMapping.ROLE_LOCAL_NAME ), + tableGroup.getNavigablePath().append( EntityIdentifierMapping.ID_ROLE_NAME ), tableGroup, null, creationState diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AbstractCompositeIdentifierMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AbstractCompositeIdentifierMapping.java index 3ff4da72e5..9b3b8fe102 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AbstractCompositeIdentifierMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/AbstractCompositeIdentifierMapping.java @@ -47,7 +47,6 @@ import org.hibernate.sql.results.graph.FetchParent; import org.hibernate.sql.results.graph.embeddable.EmbeddableValuedFetchable; import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableFetchImpl; import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableResultImpl; -import org.hibernate.type.descriptor.java.JavaType; /** * Base implementation for composite identifier mappings @@ -67,7 +66,7 @@ public abstract class AbstractCompositeIdentifierMapping EntityMappingType entityMapping, String tableExpression, MappingModelCreationProcess creationProcess) { - this.navigableRole = entityMapping.getNavigableRole().appendContainer( EntityIdentifierMapping.ROLE_LOCAL_NAME ); + this.navigableRole = entityMapping.getNavigableRole().appendContainer( EntityIdentifierMapping.ID_ROLE_NAME ); this.entityMapping = entityMapping; this.tableExpression = tableExpression; this.sessionFactory = creationProcess.getCreationContext().getSessionFactory(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EntityDiscriminatorMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EntityDiscriminatorMapping.java index 64de92e730..900398d453 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EntityDiscriminatorMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EntityDiscriminatorMapping.java @@ -29,16 +29,18 @@ import org.hibernate.sql.results.graph.basic.BasicFetch; * @author Steve Ebersole */ public interface EntityDiscriminatorMapping extends DiscriminatorMapping, FetchOptions { - String ROLE_NAME = "{discriminator}"; - String LEGACY_HQL_ROLE_NAME = "class"; + + String DISCRIMINATOR_ROLE_NAME = "{discriminator}"; + String LEGACY_DISCRIMINATOR_NAME = "class"; static boolean matchesRoleName(String name) { - return ROLE_NAME.equals( name ) || LEGACY_HQL_ROLE_NAME.equals( name ); + return DISCRIMINATOR_ROLE_NAME.equals( name ) + || LEGACY_DISCRIMINATOR_NAME.equalsIgnoreCase( name ); } @Override default String getPartName() { - return ROLE_NAME; + return DISCRIMINATOR_ROLE_NAME; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EntityIdentifierMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EntityIdentifierMapping.java index 103321ab2c..f6612255e8 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EntityIdentifierMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EntityIdentifierMapping.java @@ -25,11 +25,17 @@ import jakarta.persistence.IdClass; */ public interface EntityIdentifierMapping extends ValuedModelPart { - String ROLE_LOCAL_NAME = "{id}"; + String ID_ROLE_NAME = "{id}"; + String LEGACY_ID_NAME = "id"; + + static boolean matchesRoleName(String name) { + return LEGACY_ID_NAME.equalsIgnoreCase( name ) + || ID_ROLE_NAME.equals( name ); + } @Override default String getPartName() { - return ROLE_LOCAL_NAME; + return ID_ROLE_NAME; } /** diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/MappingModelHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/MappingModelHelper.java index cc1a2ba170..09737cabbf 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/MappingModelHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/MappingModelHelper.java @@ -6,18 +6,7 @@ */ package org.hibernate.metamodel.mapping; -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.persister.entity.UnionSubclassEntityPersister; -import org.hibernate.sql.ast.spi.SqlExpressionResolver; -import org.hibernate.sql.ast.tree.expression.ColumnReference; -import org.hibernate.sql.ast.tree.expression.Expression; -import org.hibernate.sql.ast.tree.expression.SqlTuple; -import org.hibernate.sql.ast.tree.from.TableGroup; - -import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey; /** * @author Steve Ebersole @@ -27,80 +16,79 @@ public class MappingModelHelper { private MappingModelHelper() { // disallow direct instantiation } - - public static Expression buildColumnReferenceExpression( - ModelPart modelPart, - SqlExpressionResolver sqlExpressionResolver, - SessionFactoryImplementor sessionFactory) { - return buildColumnReferenceExpression( null, modelPart, sqlExpressionResolver, sessionFactory ); - } - - public static Expression buildColumnReferenceExpression( - TableGroup tableGroup, - ModelPart modelPart, - SqlExpressionResolver sqlExpressionResolver, - SessionFactoryImplementor sessionFactory) { - final int jdbcTypeCount = modelPart.getJdbcTypeCount(); - - if ( modelPart instanceof EmbeddableValuedModelPart ) { - final List columnReferences = new ArrayList<>( jdbcTypeCount ); - modelPart.forEachSelectable( - (columnIndex, selection) -> { - final ColumnReference colRef; - final String qualifier; - if ( tableGroup == null ) { - qualifier = selection.getContainingTableExpression(); - } - else { - qualifier = tableGroup.resolveTableReference( selection.getContainingTableExpression() ).getIdentificationVariable(); - } - if ( sqlExpressionResolver == null ) { - colRef = new ColumnReference( - qualifier, - selection - ); - } - else { - colRef = (ColumnReference) sqlExpressionResolver.resolveSqlExpression( - createColumnReferenceKey( qualifier, selection ), - sqlAstProcessingState -> new ColumnReference( - qualifier, - selection - ) - ); - } - columnReferences.add( colRef ); - } - ); - return new SqlTuple( columnReferences, modelPart ); - } - else { - assert modelPart instanceof BasicValuedModelPart; - final BasicValuedModelPart basicPart = (BasicValuedModelPart) modelPart; - final String qualifier; - if ( tableGroup == null ) { - qualifier = basicPart.getContainingTableExpression(); - } - else { - qualifier = tableGroup.resolveTableReference( basicPart.getContainingTableExpression() ).getIdentificationVariable(); - } - if ( sqlExpressionResolver == null ) { - return new ColumnReference( - qualifier, - basicPart - ); - } - else { - return sqlExpressionResolver.resolveSqlExpression( - createColumnReferenceKey( qualifier, basicPart ), - sqlAstProcessingState -> new ColumnReference( - qualifier, - basicPart - ) - ); - } - } - } +// +// public static Expression buildColumnReferenceExpression( +// ModelPart modelPart, +// SqlExpressionResolver sqlExpressionResolver) { +// return buildColumnReferenceExpression( null, modelPart, sqlExpressionResolver ); +// } +// +// public static Expression buildColumnReferenceExpression( +// TableGroup tableGroup, +// ModelPart modelPart, +// SqlExpressionResolver sqlExpressionResolver) { +// final int jdbcTypeCount = modelPart.getJdbcTypeCount(); +// +// if ( modelPart instanceof EmbeddableValuedModelPart ) { +// final List columnReferences = new ArrayList<>( jdbcTypeCount ); +// modelPart.forEachSelectable( +// (columnIndex, selection) -> { +// final ColumnReference colRef; +// final String qualifier; +// if ( tableGroup == null ) { +// qualifier = selection.getContainingTableExpression(); +// } +// else { +// qualifier = tableGroup.resolveTableReference( selection.getContainingTableExpression() ).getIdentificationVariable(); +// } +// if ( sqlExpressionResolver == null ) { +// colRef = new ColumnReference( +// qualifier, +// selection +// ); +// } +// else { +// colRef = (ColumnReference) sqlExpressionResolver.resolveSqlExpression( +// createColumnReferenceKey( qualifier, selection ), +// sqlAstProcessingState -> new ColumnReference( +// qualifier, +// selection +// ) +// ); +// } +// columnReferences.add( colRef ); +// } +// ); +// return new SqlTuple( columnReferences, modelPart ); +// } +// else { +// assert modelPart instanceof BasicValuedModelPart; +// final BasicValuedModelPart basicPart = (BasicValuedModelPart) modelPart; +// final String qualifier; +// if ( tableGroup == null ) { +// qualifier = basicPart.getContainingTableExpression(); +// } +// else { +// qualifier = tableGroup.resolveTableReference( basicPart.getContainingTableExpression() ).getIdentificationVariable(); +// } +// if ( sqlExpressionResolver == null ) { +// return new ColumnReference( +// qualifier, +// basicPart +// ); +// } +// else { +// return sqlExpressionResolver.resolveSqlExpression( +// createColumnReferenceKey( qualifier, basicPart ), +// sqlAstProcessingState -> new ColumnReference( +// qualifier, +// basicPart +// ) +// ); +// } +// } +// } +// public static boolean isCompatibleModelPart(ModelPart attribute1, ModelPart attribute2) { if ( attribute1 == attribute2 ) { return true; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractDiscriminatorMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractDiscriminatorMapping.java index a1750d31f0..39bed53e05 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractDiscriminatorMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractDiscriminatorMapping.java @@ -53,7 +53,7 @@ public abstract class AbstractDiscriminatorMapping implements EntityDiscriminato this.underlyingJdbcMapping = underlyingJdbcMapping; this.entityDescriptor = entityDescriptor; - this.role = entityDescriptor.getNavigableRole().append( EntityDiscriminatorMapping.ROLE_NAME ); + this.role = entityDescriptor.getNavigableRole().append( EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME ); this.discriminatorType = discriminatorType; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractEntityCollectionPart.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractEntityCollectionPart.java index d1f93ac6a2..d4e7ba0cea 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractEntityCollectionPart.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AbstractEntityCollectionPart.java @@ -23,7 +23,6 @@ import org.hibernate.mapping.Value; import org.hibernate.metamodel.mapping.AssociationKey; import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityMappingType; -import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.persister.collection.CollectionPersister; @@ -33,7 +32,6 @@ import org.hibernate.sql.ast.spi.FromClauseAccess; import org.hibernate.sql.ast.spi.SqlAliasBase; import org.hibernate.sql.ast.spi.SqlAstCreationContext; import org.hibernate.sql.ast.spi.SqlAstCreationState; -import org.hibernate.sql.ast.spi.SqlExpressionResolver; import org.hibernate.sql.ast.tree.from.PluralTableGroup; import org.hibernate.sql.ast.tree.from.StandardTableGroup; import org.hibernate.sql.ast.tree.from.TableGroup; @@ -376,7 +374,7 @@ public abstract class AbstractEntityCollectionPart implements EntityCollectionPa if ( referencedPropertyName == null ) { final Set targetKeyPropertyNames = new HashSet<>( 2 ); - targetKeyPropertyNames.add( EntityIdentifierMapping.ROLE_LOCAL_NAME ); + targetKeyPropertyNames.add( EntityIdentifierMapping.ID_ROLE_NAME ); final Type propertyType; if ( entityBinding.getIdentifierMapper() == null ) { propertyType = entityBinding.getIdentifier().getType(); @@ -396,7 +394,7 @@ public abstract class AbstractEntityCollectionPart implements EntityCollectionPa ); ToOneAttributeMapping.addPrefixedPropertyNames( targetKeyPropertyNames, - EntityIdentifierMapping.ROLE_LOCAL_NAME, + EntityIdentifierMapping.ID_ROLE_NAME, propertyType, creationProcess.getCreationContext().getSessionFactory() ); @@ -451,7 +449,7 @@ public abstract class AbstractEntityCollectionPart implements EntityCollectionPa ); ToOneAttributeMapping.addPrefixedPropertyNames( targetKeyPropertyNames, - EntityIdentifierMapping.ROLE_LOCAL_NAME, + EntityIdentifierMapping.ID_ROLE_NAME, propertyType, creationProcess.getCreationContext().getSessionFactory() ); @@ -459,7 +457,7 @@ public abstract class AbstractEntityCollectionPart implements EntityCollectionPa } else { final Set targetKeyPropertyNames = new HashSet<>( 2 ); - targetKeyPropertyNames.add( EntityIdentifierMapping.ROLE_LOCAL_NAME ); + targetKeyPropertyNames.add( EntityIdentifierMapping.ID_ROLE_NAME ); targetKeyPropertyNames.add( referencedPropertyName ); final String mapsIdAttributeName; if ( ( mapsIdAttributeName = ToOneAttributeMapping.findMapsIdPropertyName( elementTypeDescriptor, referencedPropertyName ) ) != null ) { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AnyDiscriminatorPart.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AnyDiscriminatorPart.java index 90243d6ce2..22d66ad58c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AnyDiscriminatorPart.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/AnyDiscriminatorPart.java @@ -42,7 +42,6 @@ import org.hibernate.sql.results.graph.FetchOptions; import org.hibernate.sql.results.graph.FetchParent; import org.hibernate.sql.results.graph.basic.BasicFetch; import org.hibernate.type.BasicType; -import org.hibernate.type.descriptor.converter.spi.BasicValueConverter; import org.hibernate.type.descriptor.java.ClassJavaType; import org.hibernate.type.descriptor.java.JavaType; @@ -52,7 +51,7 @@ import org.hibernate.type.descriptor.java.JavaType; * @author Steve Ebersole */ public class AnyDiscriminatorPart implements DiscriminatorMapping, FetchOptions { - public static final String ROLE_NAME = EntityDiscriminatorMapping.ROLE_NAME; + public static final String ROLE_NAME = EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME; private final NavigableRole navigableRole; private final DiscriminatedAssociationModelPart declaringType; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/BasicEntityIdentifierMappingImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/BasicEntityIdentifierMappingImpl.java index 87e6d551dc..0d8a8f0421 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/BasicEntityIdentifierMappingImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/BasicEntityIdentifierMappingImpl.java @@ -113,7 +113,7 @@ public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMa propertyAccess = entityPersister.getRepresentationStrategy() .resolvePropertyAccess( bootEntityDescriptor.getIdentifierProperty() ); - idRole = entityPersister.getNavigableRole().append( EntityIdentifierMapping.ROLE_LOCAL_NAME ); + idRole = entityPersister.getNavigableRole().append( EntityIdentifierMapping.ID_ROLE_NAME ); sessionFactory = creationProcess.getCreationContext().getSessionFactory(); unsavedStrategy = UnsavedValueFactory.getUnsavedIdentifierValue( diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/CaseStatementDiscriminatorMappingImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/CaseStatementDiscriminatorMappingImpl.java index b89c3a0441..83c2eb176f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/CaseStatementDiscriminatorMappingImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/CaseStatementDiscriminatorMappingImpl.java @@ -188,7 +188,7 @@ public class CaseStatementDiscriminatorMappingImpl extends AbstractDiscriminator public String getSelectionExpression() { // this *should* only be used to create the sql-expression key, so just // using the ROLE_NAME should be fine - return ROLE_NAME; + return DISCRIMINATOR_ROLE_NAME; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/IdClassEmbeddable.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/IdClassEmbeddable.java index 5c79f359eb..50f68de205 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/IdClassEmbeddable.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/IdClassEmbeddable.java @@ -77,7 +77,7 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden final PropertyAccess propertyAccess = PropertyAccessStrategyMapImpl.INSTANCE.buildPropertyAccess( null, - EntityIdentifierMapping.ROLE_LOCAL_NAME, + EntityIdentifierMapping.ID_ROLE_NAME, true ); final AttributeMetadata attributeMetadata = MappingModelCreationHelper.getAttributeMetadata( propertyAccess @@ -86,7 +86,7 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden embedded = new EmbeddedAttributeMapping( NavigablePath.IDENTIFIER_MAPPER_PROPERTY, identifiedEntityMapping.getNavigableRole() - .append( EntityIdentifierMapping.ROLE_LOCAL_NAME ) + .append( EntityIdentifierMapping.ID_ROLE_NAME ) .append( NavigablePath.IDENTIFIER_MAPPER_PROPERTY ), -1, -1, diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/InverseNonAggregatedIdentifierMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/InverseNonAggregatedIdentifierMapping.java index 26fdb4aa0d..c04784822a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/InverseNonAggregatedIdentifierMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/InverseNonAggregatedIdentifierMapping.java @@ -304,7 +304,7 @@ public class InverseNonAggregatedIdentifierMapping extends EmbeddedAttributeMapp @Override public String getFetchableName() { - return EntityIdentifierMapping.ROLE_LOCAL_NAME; + return EntityIdentifierMapping.ID_ROLE_NAME; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java index 3e2a618ad4..ca24bbc25a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java @@ -379,7 +379,7 @@ public class NonAggregatedIdentifierMappingImpl extends AbstractCompositeIdentif @Override public String getFetchableName() { - return EntityIdentifierMapping.ROLE_LOCAL_NAME; + return EntityIdentifierMapping.ID_ROLE_NAME; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SingleAttributeIdentifierMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SingleAttributeIdentifierMapping.java index b353f80910..f6fad89adc 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SingleAttributeIdentifierMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/SingleAttributeIdentifierMapping.java @@ -30,7 +30,7 @@ public interface SingleAttributeIdentifierMapping extends EntityIdentifierMappin @Override default String getPartName() { - return ROLE_LOCAL_NAME; + return ID_ROLE_NAME; } @Override 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 7579b607a6..21dc1c12f4 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 @@ -390,7 +390,7 @@ public class ToOneAttributeMapping if ( referencedPropertyName == null ) { final Set targetKeyPropertyNames = new HashSet<>( 2 ); - targetKeyPropertyNames.add( EntityIdentifierMapping.ROLE_LOCAL_NAME ); + targetKeyPropertyNames.add( EntityIdentifierMapping.ID_ROLE_NAME ); final PersistentClass entityBinding = bootValue.getBuildingContext().getMetadataCollector() .getEntityBinding( entityMappingType.getEntityName() ); final Type propertyType; @@ -413,13 +413,13 @@ public class ToOneAttributeMapping ); addPrefixedPropertyNames( targetKeyPropertyNames, - EntityIdentifierMapping.ROLE_LOCAL_NAME, + EntityIdentifierMapping.ID_ROLE_NAME, propertyType, declaringEntityPersister.getFactory() ); } else { - this.targetKeyPropertyName = EntityIdentifierMapping.ROLE_LOCAL_NAME; + this.targetKeyPropertyName = EntityIdentifierMapping.ID_ROLE_NAME; addPrefixedPropertyPaths( targetKeyPropertyNames, null, @@ -467,7 +467,7 @@ public class ToOneAttributeMapping ); addPrefixedPropertyNames( targetKeyPropertyNames, - EntityIdentifierMapping.ROLE_LOCAL_NAME, + EntityIdentifierMapping.ID_ROLE_NAME, propertyType, declaringEntityPersister.getFactory() ); @@ -685,7 +685,7 @@ public class ToOneAttributeMapping ); addPrefixedPropertyNames( targetKeyPropertyNames, - EntityIdentifierMapping.ROLE_LOCAL_NAME, + EntityIdentifierMapping.ID_ROLE_NAME, type, factory ); @@ -732,17 +732,17 @@ public class ToOneAttributeMapping final String newFkPrefix; if ( prefix == null ) { newPrefix = propertyName; - newPkPrefix = propertyName + "." + EntityIdentifierMapping.ROLE_LOCAL_NAME; + newPkPrefix = propertyName + "." + EntityIdentifierMapping.ID_ROLE_NAME; newFkPrefix = ForeignKeyDescriptor.PART_NAME; } else if ( propertyName == null ) { newPrefix = prefix; - newPkPrefix = prefix + "." + EntityIdentifierMapping.ROLE_LOCAL_NAME; + newPkPrefix = prefix + "." + EntityIdentifierMapping.ID_ROLE_NAME; newFkPrefix = prefix + "." + ForeignKeyDescriptor.PART_NAME; } else { newPrefix = prefix + "." + propertyName; - newPkPrefix = prefix + "." + EntityIdentifierMapping.ROLE_LOCAL_NAME; + newPkPrefix = prefix + "." + EntityIdentifierMapping.ID_ROLE_NAME; newFkPrefix = prefix + "." + ForeignKeyDescriptor.PART_NAME; } addPrefixedPropertyNames( targetKeyPropertyNames, newPrefix, identifierOrUniqueKeyType, factory ); @@ -752,11 +752,11 @@ public class ToOneAttributeMapping final String newEmbeddedPkPrefix; final String newEmbeddedFkPrefix; if ( prefix == null ) { - newEmbeddedPkPrefix = EntityIdentifierMapping.ROLE_LOCAL_NAME; + newEmbeddedPkPrefix = EntityIdentifierMapping.ID_ROLE_NAME; newEmbeddedFkPrefix = ForeignKeyDescriptor.PART_NAME; } else { - newEmbeddedPkPrefix = prefix + "." + EntityIdentifierMapping.ROLE_LOCAL_NAME; + newEmbeddedPkPrefix = prefix + "." + EntityIdentifierMapping.ID_ROLE_NAME; newEmbeddedFkPrefix = prefix + "." + ForeignKeyDescriptor.PART_NAME; } addPrefixedPropertyNames( targetKeyPropertyNames, newEmbeddedPkPrefix, identifierOrUniqueKeyType, factory ); @@ -876,7 +876,7 @@ public class ToOneAttributeMapping fkPart = foreignKeyDescriptor.getTargetPart(); } if ( fkPart instanceof EmbeddableValuedModelPart && fkPart instanceof VirtualModelPart - && !EntityIdentifierMapping.ROLE_LOCAL_NAME.equals( name ) + && !EntityIdentifierMapping.ID_ROLE_NAME.equals( name ) && !ForeignKeyDescriptor.PART_NAME.equals( name ) && !ForeignKeyDescriptor.TARGET_PART_NAME.equals( name ) && !fkPart.getPartName().equals( name ) ) { @@ -1138,7 +1138,7 @@ public class ToOneAttributeMapping NavigablePath navigablePath = parentNavigablePath.trimSuffix( bidirectionalAttributePath ); if ( navigablePath != null ) { final String localName = navigablePath.getLocalName(); - if ( localName.equals( EntityIdentifierMapping.ROLE_LOCAL_NAME ) + if ( localName.equals( EntityIdentifierMapping.ID_ROLE_NAME ) || localName.equals( ForeignKeyDescriptor.PART_NAME ) || localName.equals( ForeignKeyDescriptor.TARGET_PART_NAME ) ) { navigablePath = navigablePath.getParent(); @@ -1759,7 +1759,7 @@ public class ToOneAttributeMapping if ( referencedPropertyName == null ) { //noinspection unchecked return new EntityDelayedResultImpl( - navigablePath.append( EntityIdentifierMapping.ROLE_LOCAL_NAME ), + navigablePath.append( EntityIdentifierMapping.ID_ROLE_NAME ), this, tableGroupToUse, creationState diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractDomainType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractDomainType.java index 0d0768fe3d..cd213af1b3 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractDomainType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractDomainType.java @@ -6,23 +6,16 @@ */ package org.hibernate.metamodel.model.domain; -import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; import org.hibernate.type.descriptor.java.JavaType; /** * @author Steve Ebersole */ public abstract class AbstractDomainType implements SimpleDomainType { - private final JpaMetamodelImplementor domainMetamodel; private final JavaType javaType; - public AbstractDomainType(JavaType javaType, JpaMetamodelImplementor domainMetamodel) { + public AbstractDomainType(JavaType javaType) { this.javaType = javaType; - this.domainMetamodel = domainMetamodel; - } - - protected JpaMetamodelImplementor jpaMetamodel() { - return domainMetamodel; } @Override @@ -32,7 +25,7 @@ public abstract class AbstractDomainType implements SimpleDomainType { @Override public Class getJavaType() { - return this.getExpressibleJavaType().getJavaTypeClass(); + return getExpressibleJavaType().getJavaTypeClass(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractIdentifiableType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractIdentifiableType.java index 71e59bfe6f..a1dcbd340b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractIdentifiableType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractIdentifiableType.java @@ -30,13 +30,16 @@ import org.hibernate.type.descriptor.java.spi.PrimitiveJavaType; import org.jboss.logging.Logger; /** - * Defines commonality for the JPA {@link IdentifiableType} types. JPA defines - * identifiable types as entities or mapped-superclasses. Basically things to which an - * identifier can be attached. + * Functionality common to all implementations of {@link IdentifiableType}. + *

+ * An identifiable type is one which may have an identifier attribute, that + * is, an {@linkplain jakarta.persistence.Entity entity type} or a + * {@linkplain jakarta.persistence.MappedSuperclass mapped superclass}. * - * @apiNote Currently we only really have support for direct entities in the Hibernate metamodel - * as the information for them is consumed into the closest actual entity subclass(es) in the - * internal Hibernate mapping-metamodel. + * @apiNote Currently we only really have support for direct entities in the + * Hibernate metamodel as the information for them is consumed into + * the closest actual entity subclass(es) in the internal Hibernate + * mapping metamodel. * * @author Steve Ebersole */ @@ -65,8 +68,8 @@ public abstract class AbstractIdentifiableType boolean hasIdClass, boolean hasIdentifierProperty, boolean versioned, - JpaMetamodelImplementor jpaMetamodel) { - super( typeName, javaType, superType, jpaMetamodel ); + JpaMetamodelImplementor metamodel) { + super( typeName, javaType, superType, metamodel ); this.hasIdClass = hasIdClass; this.hasIdentifierProperty = hasIdentifierProperty; this.isVersioned = versioned; @@ -97,7 +100,6 @@ public abstract class AbstractIdentifiableType } @Override - @SuppressWarnings("unchecked") public IdentifiableDomainType getSuperType() { // overridden simply to perform the cast return (IdentifiableDomainType) super.getSuperType(); @@ -112,7 +114,7 @@ public abstract class AbstractIdentifiableType @SuppressWarnings("unchecked") public SingularPersistentAttribute getId(Class javaType) { ensureNoIdClass(); - SingularPersistentAttribute id = findIdAttribute(); + SingularPersistentAttribute id = findIdAttribute(); if ( id != null ) { checkType( id, javaType ); } @@ -129,28 +131,23 @@ public abstract class AbstractIdentifiableType @Override - @SuppressWarnings("unchecked") - public SingularPersistentAttribute findIdAttribute() { + public SingularPersistentAttribute findIdAttribute() { if ( id != null ) { return id; } - else { - if ( getSuperType() != null ) { - SingularPersistentAttribute id = getSuperType().findIdAttribute(); - if ( id != null ) { - return (SingularPersistentAttribute) id; - } - } + else if ( getSuperType() != null ) { + return getSuperType().findIdAttribute(); + } + else { + return null; } - - return null; } private void checkType(SingularPersistentAttribute attribute, Class javaType) { if ( !javaType.isAssignableFrom( attribute.getType().getJavaType() ) ) { final JavaType attributeJavaType = attribute.getAttributeJavaType(); if ( !( attributeJavaType instanceof PrimitiveJavaType ) - || ( (PrimitiveJavaType) attributeJavaType ).getPrimitiveClass() != javaType ) { + || ( (PrimitiveJavaType) attributeJavaType ).getPrimitiveClass() != javaType ) { throw new IllegalArgumentException( String.format( "Attribute [%s#%s : %s] not castable to requested type [%s]", @@ -177,7 +174,7 @@ public abstract class AbstractIdentifiableType @Override public SimpleDomainType getIdType() { - final SingularPersistentAttribute id = findIdAttribute(); + final SingularPersistentAttribute id = findIdAttribute(); if ( id != null ) { return id.getType(); } @@ -413,7 +410,7 @@ public abstract class AbstractIdentifiableType final SimpleDomainType type = id.getType(); if ( type instanceof BasicDomainType ) { return new BasicSqmPathSource<>( - EntityIdentifierMapping.ROLE_LOCAL_NAME, + EntityIdentifierMapping.ID_ROLE_NAME, (SqmPathSource) id, (BasicDomainType) type, type.getExpressibleJavaType(), @@ -425,7 +422,7 @@ public abstract class AbstractIdentifiableType assert type instanceof EmbeddableDomainType; final EmbeddableDomainType compositeType = (EmbeddableDomainType) type; return new EmbeddedSqmPathSource<>( - EntityIdentifierMapping.ROLE_LOCAL_NAME, + EntityIdentifierMapping.ID_ROLE_NAME, (SqmPathSource) id, compositeType, Bindable.BindableType.SINGULAR_ATTRIBUTE, @@ -437,7 +434,7 @@ public abstract class AbstractIdentifiableType // non-aggregate composite id if ( idClassType == null ) { return new NonAggregatedCompositeSqmPathSource<>( - EntityIdentifierMapping.ROLE_LOCAL_NAME, + EntityIdentifierMapping.ID_ROLE_NAME, null, Bindable.BindableType.SINGULAR_ATTRIBUTE, this @@ -445,7 +442,7 @@ public abstract class AbstractIdentifiableType } else { return new EmbeddedSqmPathSource<>( - EntityIdentifierMapping.ROLE_LOCAL_NAME, + EntityIdentifierMapping.ID_ROLE_NAME, null, idClassType, Bindable.BindableType.SINGULAR_ATTRIBUTE, diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractManagedType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractManagedType.java index 399052dfad..3a0434c6d8 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractManagedType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/AbstractManagedType.java @@ -10,13 +10,11 @@ import java.io.ObjectStreamException; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.function.Consumer; @@ -29,22 +27,16 @@ import jakarta.persistence.metamodel.PluralAttribute; import jakarta.persistence.metamodel.SetAttribute; import jakarta.persistence.metamodel.SingularAttribute; -import org.hibernate.graph.internal.SubGraphImpl; -import org.hibernate.graph.spi.SubGraphImplementor; -import org.hibernate.internal.util.collections.CollectionHelper; -import org.hibernate.metamodel.MappingMetamodel; import org.hibernate.metamodel.RepresentationMode; -import org.hibernate.metamodel.mapping.EntityMappingType; -import org.hibernate.metamodel.mapping.MappingModelHelper; import org.hibernate.metamodel.model.domain.internal.AttributeContainer; -import org.hibernate.metamodel.model.domain.internal.DomainModelHelper; import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; -import org.hibernate.query.PathException; import org.hibernate.type.descriptor.java.JavaType; +import static java.util.Collections.emptySet; +import static org.hibernate.internal.util.collections.CollectionHelper.isEmpty; + /** - * Commonality for Hibernate's implementations of the JPA {@link ManagedType} - * contract. + * Functionality common to all implementations of {@link ManagedType}. * * @author Steve Ebersole */ @@ -54,6 +46,7 @@ public abstract class AbstractManagedType private final String hibernateTypeName; private final ManagedDomainType superType; private final RepresentationMode representationMode; + private final JpaMetamodelImplementor metamodel; private final Map> declaredSingularAttributes = new LinkedHashMap<>(); private volatile Map> declaredPluralAttributes ; @@ -65,10 +58,11 @@ public abstract class AbstractManagedType String hibernateTypeName, JavaType javaType, ManagedDomainType superType, - JpaMetamodelImplementor domainMetamodel) { - super( javaType, domainMetamodel ); + JpaMetamodelImplementor metamodel) { + super( javaType ); this.hibernateTypeName = hibernateTypeName; this.superType = superType; + this.metamodel = metamodel; if ( superType != null ) { superType.addSubType( this ); } @@ -94,7 +88,7 @@ public abstract class AbstractManagedType } @Override - public void addSubType(ManagedDomainType subType){ + public void addSubType(ManagedDomainType subType){ subTypes.add( subType ); } @@ -104,11 +98,10 @@ public abstract class AbstractManagedType } @Override - @SuppressWarnings("unchecked") - public void visitAttributes(Consumer> action) { + public void visitAttributes(Consumer> action) { visitDeclaredAttributes( action ); if ( getSuperType() != null ) { - getSuperType().visitAttributes( (Consumer) action ); + getSuperType().visitAttributes( action ); } } @@ -123,32 +116,30 @@ public abstract class AbstractManagedType @Override public Set> getAttributes() { final HashSet> attributes = new LinkedHashSet<>( getDeclaredAttributes() ); - if ( getSuperType() != null ) { attributes.addAll( getSuperType().getAttributes() ); } - return attributes; } @Override public Set> getDeclaredAttributes() { - final boolean isDeclaredSingularAttributesEmpty = CollectionHelper.isEmpty( declaredSingularAttributes ); - final boolean isDeclaredPluralAttributes = CollectionHelper.isEmpty( declaredPluralAttributes ); + final boolean isDeclaredSingularAttributesEmpty = isEmpty( declaredSingularAttributes ); + final boolean isDeclaredPluralAttributes = isEmpty( declaredPluralAttributes ); if ( isDeclaredSingularAttributesEmpty && isDeclaredPluralAttributes ) { - return Collections.emptySet(); + return emptySet(); } - final HashSet> attributes; - if ( !isDeclaredSingularAttributesEmpty ) { - attributes = new LinkedHashSet<>( declaredSingularAttributes.values() ); + else if ( !isDeclaredSingularAttributesEmpty ) { + final HashSet> attributes = + new LinkedHashSet<>( declaredSingularAttributes.values() ); if ( !isDeclaredPluralAttributes ) { attributes.addAll( declaredPluralAttributes.values() ); } + return attributes; } else { - attributes = new LinkedHashSet<>( declaredPluralAttributes.values() ); + return new LinkedHashSet<>( declaredPluralAttributes.values() ); } - return attributes; } @Override @@ -161,56 +152,16 @@ public abstract class AbstractManagedType @Override public PersistentAttribute findAttribute(String name) { // first look at declared attributes - PersistentAttribute attribute = findDeclaredAttribute( name ); + final PersistentAttribute attribute = findDeclaredAttribute( name ); if ( attribute != null ) { return attribute; } if ( getSuperType() != null ) { - attribute = getSuperType().findAttributeInSuperTypes( name ); - if ( attribute != null ) { - return attribute; - } + return getSuperType().findAttributeInSuperTypes( name ); } - for ( ManagedDomainType subType : subTypes ) { - PersistentAttribute subTypeAttribute = subType.findSubTypesAttribute( name ); - if ( subTypeAttribute != null ) { - if ( attribute != null && !isCompatible( attribute, subTypeAttribute ) ) { - throw new PathException( - String.format( - Locale.ROOT, - "Could not resolve attribute '%s' of '%s' due to the attribute being declared in multiple subtypes '%s' and '%s'", - name, - getTypeName(), - attribute.getDeclaringType().getTypeName(), - subTypeAttribute.getDeclaringType().getTypeName() - ) - ); - } - attribute = subTypeAttribute; - } - } - - return attribute; - } - - private boolean isCompatible(PersistentAttribute attribute1, PersistentAttribute attribute2) { - if ( attribute1 == attribute2 ) { - return true; - } - final MappingMetamodel runtimeMetamodels = jpaMetamodel().getMappingMetamodel(); - final EntityMappingType entity1 = runtimeMetamodels.getEntityDescriptor( - attribute1.getDeclaringType().getTypeName() - ); - final EntityMappingType entity2 = runtimeMetamodels.getEntityDescriptor( - attribute2.getDeclaringType().getTypeName() - ); - - return entity1 != null && entity2 != null && MappingModelHelper.isCompatibleModelPart( - entity1.findSubPart( attribute1.getName() ), - entity2.findSubPart( attribute2.getName() ) - ); + return null; } @Override @@ -228,15 +179,15 @@ public abstract class AbstractManagedType } @Override - public PersistentAttribute findSubTypesAttribute(String name) { + public PersistentAttribute findSubTypesAttribute(String name) { // first look at declared attributes - PersistentAttribute attribute = findDeclaredAttribute( name ); + final PersistentAttribute attribute = findDeclaredAttribute( name ); if ( attribute != null ) { return attribute; } for ( ManagedDomainType subType : subTypes ) { - PersistentAttribute subTypeAttribute = subType.findAttribute( name ); + final PersistentAttribute subTypeAttribute = subType.findAttribute( name ); if ( subTypeAttribute != null ) { return subTypeAttribute; } @@ -248,19 +199,14 @@ public abstract class AbstractManagedType @Override public PersistentAttribute findDeclaredAttribute(String name) { // try singular attribute - PersistentAttribute attribute = declaredSingularAttributes.get( name ); + final PersistentAttribute attribute = declaredSingularAttributes.get( name ); if ( attribute != null ) { return attribute; } // next plural - if ( declaredPluralAttributes == null ) { - return null; - } - attribute = declaredPluralAttributes.get( name ); - //noinspection RedundantIfStatement - if ( attribute != null ) { - return attribute; + if ( declaredPluralAttributes != null ) { + return declaredPluralAttributes.get( name ); } return null; @@ -326,48 +272,49 @@ public abstract class AbstractManagedType } @Override - @SuppressWarnings("unchecked") public SingularPersistentAttribute getSingularAttribute(String name, Class type) { - SingularAttribute attribute = findSingularAttribute( name ); - checkTypeForSingleAttribute( attribute, name, type ); - return (SingularPersistentAttribute) attribute; + return checkTypeForSingleAttribute( findSingularAttribute( name ), name, type ); } @Override - @SuppressWarnings("unchecked") public SingularAttribute getDeclaredSingularAttribute(String name) { - final SingularAttribute attr = findDeclaredSingularAttribute( name ); + final SingularAttribute attr = findDeclaredSingularAttribute( name ); checkNotNull( "SingularAttribute", attr, name ); return attr; } @Override - public SingularPersistentAttribute findDeclaredSingularAttribute(String name) { + public SingularPersistentAttribute findDeclaredSingularAttribute(String name) { return declaredSingularAttributes.get( name ); } @Override - @SuppressWarnings("unchecked") public SingularPersistentAttribute getDeclaredSingularAttribute(String name, Class javaType) { - final SingularAttribute attr = findDeclaredSingularAttribute( name ); - checkTypeForSingleAttribute( attr, name, javaType ); - return (SingularPersistentAttribute) attr; + return checkTypeForSingleAttribute( findDeclaredSingularAttribute( name ), name, javaType ); } - private void checkTypeForSingleAttribute( - SingularAttribute attribute, + private SingularPersistentAttribute checkTypeForSingleAttribute( + SingularPersistentAttribute attribute, String name, Class javaType) { - if ( attribute == null || ( javaType != null && !attribute.getBindableJavaType().equals( javaType ) ) ) { - if ( isPrimitiveVariant( attribute, javaType ) ) { - return; - } + if ( attribute == null || !hasMatchingReturnType( attribute, javaType ) ) { throw new IllegalArgumentException( "SingularAttribute named " + name + ( javaType != null ? " and of type " + javaType.getName() : "" ) + " is not present" ); } + else { + @SuppressWarnings("unchecked") + SingularPersistentAttribute narrowed = (SingularPersistentAttribute) attribute; + return narrowed; + } + } + + private boolean hasMatchingReturnType(SingularAttribute attribute, Class javaType) { + return javaType == null + || attribute.getBindableJavaType().equals( javaType ) + || isPrimitiveVariant( attribute, javaType ); } protected boolean isPrimitiveVariant(SingularAttribute attribute, Class javaType) { @@ -378,24 +325,24 @@ public abstract class AbstractManagedType if ( declaredType.isPrimitive() ) { return ( Boolean.class.equals( javaType ) && Boolean.TYPE.equals( declaredType ) ) - || ( Character.class.equals( javaType ) && Character.TYPE.equals( declaredType ) ) - || ( Byte.class.equals( javaType ) && Byte.TYPE.equals( declaredType ) ) - || ( Short.class.equals( javaType ) && Short.TYPE.equals( declaredType ) ) - || ( Integer.class.equals( javaType ) && Integer.TYPE.equals( declaredType ) ) - || ( Long.class.equals( javaType ) && Long.TYPE.equals( declaredType ) ) - || ( Float.class.equals( javaType ) && Float.TYPE.equals( declaredType ) ) - || ( Double.class.equals( javaType ) && Double.TYPE.equals( declaredType ) ); + || ( Character.class.equals( javaType ) && Character.TYPE.equals( declaredType ) ) + || ( Byte.class.equals( javaType ) && Byte.TYPE.equals( declaredType ) ) + || ( Short.class.equals( javaType ) && Short.TYPE.equals( declaredType ) ) + || ( Integer.class.equals( javaType ) && Integer.TYPE.equals( declaredType ) ) + || ( Long.class.equals( javaType ) && Long.TYPE.equals( declaredType ) ) + || ( Float.class.equals( javaType ) && Float.TYPE.equals( declaredType ) ) + || ( Double.class.equals( javaType ) && Double.TYPE.equals( declaredType ) ); } if ( javaType.isPrimitive() ) { return ( Boolean.class.equals( declaredType ) && Boolean.TYPE.equals( javaType ) ) - || ( Character.class.equals( declaredType ) && Character.TYPE.equals( javaType ) ) - || ( Byte.class.equals( declaredType ) && Byte.TYPE.equals( javaType ) ) - || ( Short.class.equals( declaredType ) && Short.TYPE.equals( javaType ) ) - || ( Integer.class.equals( declaredType ) && Integer.TYPE.equals( javaType ) ) - || ( Long.class.equals( declaredType ) && Long.TYPE.equals( javaType ) ) - || ( Float.class.equals( declaredType ) && Float.TYPE.equals( javaType ) ) - || ( Double.class.equals( declaredType ) && Double.TYPE.equals( javaType ) ); + || ( Character.class.equals( declaredType ) && Character.TYPE.equals( javaType ) ) + || ( Byte.class.equals( declaredType ) && Byte.TYPE.equals( javaType ) ) + || ( Short.class.equals( declaredType ) && Short.TYPE.equals( javaType ) ) + || ( Integer.class.equals( declaredType ) && Integer.TYPE.equals( javaType ) ) + || ( Long.class.equals( declaredType ) && Long.TYPE.equals( javaType ) ) + || ( Float.class.equals( declaredType ) && Float.TYPE.equals( javaType ) ) + || ( Double.class.equals( declaredType ) && Double.TYPE.equals( javaType ) ); } return false; @@ -419,7 +366,7 @@ public abstract class AbstractManagedType @Override public Set> getDeclaredPluralAttributes() { return declaredPluralAttributes == null - ? Collections.emptySet() + ? emptySet() : new HashSet<>( declaredPluralAttributes.values() ); } @@ -438,7 +385,7 @@ public abstract class AbstractManagedType } @Override - public PluralPersistentAttribute findDeclaredPluralAttribute(String name) { + public PluralPersistentAttribute findDeclaredPluralAttribute(String name) { return declaredPluralAttributes == null ? null : declaredPluralAttributes.get( name ); } @@ -473,7 +420,7 @@ public abstract class AbstractManagedType } @Override - public PersistentAttribute findDeclaredConcreteGenericAttribute(String name) { + public PersistentAttribute findDeclaredConcreteGenericAttribute(String name) { return declaredConcreteGenericAttributes == null ? null : declaredConcreteGenericAttributes.get( name ); } @@ -682,26 +629,11 @@ public abstract class AbstractManagedType } - @Override - public SubGraphImplementor makeSubGraph() { - return new SubGraphImpl<>( this, true); - } - - @Override - public ManagedDomainType findSubType(String subTypeName) { - return DomainModelHelper.resolveSubType( this, subTypeName, jpaMetamodel() ); - } - - @Override - public ManagedDomainType findSubType(Class subType) { - return DomainModelHelper.resolveSubType( this, subType, jpaMetamodel() ); - } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Serialization protected Object writeReplace() throws ObjectStreamException { - return new SerialForm( jpaMetamodel(), getJavaType() ); + return new SerialForm( metamodel, getJavaType() ); } private static class SerialForm implements Serializable { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/IdentifiableDomainType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/IdentifiableDomainType.java index 2905f8186a..8fa79a82ce 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/IdentifiableDomainType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/IdentifiableDomainType.java @@ -45,7 +45,7 @@ public interface IdentifiableDomainType extends ManagedDomainType, Identif boolean hasIdClass(); - SingularPersistentAttribute findIdAttribute(); + SingularPersistentAttribute findIdAttribute(); void visitIdClassAttributes(Consumer> action); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/ManagedDomainType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/ManagedDomainType.java index 59cd63f631..00c223f4c4 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/ManagedDomainType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/ManagedDomainType.java @@ -9,14 +9,13 @@ package org.hibernate.metamodel.model.domain; import java.util.Collection; import java.util.function.Consumer; -import org.hibernate.graph.spi.SubGraphImplementor; import org.hibernate.metamodel.RepresentationMode; import org.hibernate.query.sqm.SqmExpressible; import jakarta.persistence.metamodel.ManagedType; /** - * Hibernate extension to the JPA {@link ManagedType} contract + * Extensions to the JPA-defined {@link ManagedType} contract. * * @author Steve Ebersole */ @@ -24,9 +23,9 @@ public interface ManagedDomainType extends SqmExpressible, DomainType, /** * Get the type name. * - * Generally speaking, this returns the name of the Java class. However, for - * dynamic models ({@link RepresentationMode#MAP}), this returns the symbolic name - * since the Java type is {@link java.util.Map} + * @apiNote This usually returns the name of the Java class. However, for + * {@linkplain RepresentationMode#MAP dynamic models}, this returns + * the symbolic name since the Java type is {@link java.util.Map}. * * @return The type name. * @@ -37,16 +36,18 @@ public interface ManagedDomainType extends SqmExpressible, DomainType, RepresentationMode getRepresentationMode(); /** - * This type's super type descriptor. Note : we define this on the managed - * type descriptor in anticipation of supporting embeddable inheritance + * The descriptor of the supertype of this type. + * + * @apiNote we define this here in anticipation of eventually supporting + * embeddable inheritance */ ManagedDomainType getSuperType(); Collection> getSubTypes(); - void addSubType(ManagedDomainType subType); + void addSubType(ManagedDomainType subType); - void visitAttributes(Consumer> action); + void visitAttributes(Consumer> action); void visitDeclaredAttributes(Consumer> action); @Override @@ -57,7 +58,7 @@ public interface ManagedDomainType extends SqmExpressible, DomainType, PersistentAttribute findAttribute(String name); - PersistentAttribute findSubTypesAttribute(String name); + PersistentAttribute findSubTypesAttribute(String name); PersistentAttribute findAttributeInSuperTypes(String name); SingularPersistentAttribute findSingularAttribute(String name); @@ -65,13 +66,7 @@ public interface ManagedDomainType extends SqmExpressible, DomainType, PersistentAttribute findConcreteGenericAttribute(String name); PersistentAttribute findDeclaredAttribute(String name); - SingularPersistentAttribute findDeclaredSingularAttribute(String name); - PluralPersistentAttribute findDeclaredPluralAttribute(String name); - PersistentAttribute findDeclaredConcreteGenericAttribute(String name); - - SubGraphImplementor makeSubGraph(); - SubGraphImplementor makeSubGraph(Class subClassType); - - ManagedDomainType findSubType(String subTypeName); - ManagedDomainType findSubType(Class subType); + SingularPersistentAttribute findDeclaredSingularAttribute(String name); + PluralPersistentAttribute findDeclaredPluralAttribute(String name); + PersistentAttribute findDeclaredConcreteGenericAttribute(String name); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractPluralAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractPluralAttribute.java index 38d45a5df3..4690de1e9c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractPluralAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractPluralAttribute.java @@ -16,6 +16,7 @@ import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; import org.hibernate.metamodel.model.domain.SimpleDomainType; +import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; import org.hibernate.spi.NavigablePath; import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.internal.SqmMappingModelHelper; @@ -86,6 +87,14 @@ public abstract class AbstractPluralAttribute return elementPathSource.findSubPathSource( name ); } + @Override + public SqmPathSource findSubPathSource(String name, JpaMetamodelImplementor metamodel) { + if ( CollectionPart.Nature.ELEMENT.getName().equals( name ) ) { + return elementPathSource; + } + return elementPathSource.findSubPathSource( name, metamodel ); + } + @Override public SqmPathSource getIntermediatePathSource(SqmPathSource pathSource) { return pathSource.getPathName().equals( elementPathSource.getPathName() ) ? null : elementPathSource; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DiscriminatorSqmPathSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DiscriminatorSqmPathSource.java index 4f3795ad1f..ab58232758 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DiscriminatorSqmPathSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DiscriminatorSqmPathSource.java @@ -29,7 +29,7 @@ public class DiscriminatorSqmPathSource extends AbstractSqmPathSource DomainType discriminatorValueType, EntityDomainType entityDomainType, EntityMappingType entityMapping) { - super( EntityDiscriminatorMapping.ROLE_NAME, null, discriminatorValueType, BindableType.SINGULAR_ATTRIBUTE ); + super( EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME, null, discriminatorValueType, BindableType.SINGULAR_ATTRIBUTE ); this.entityDomainType = entityDomainType; this.entityMapping = entityMapping; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DomainModelHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DomainModelHelper.java index fd90afd749..259a394a8b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DomainModelHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/DomainModelHelper.java @@ -7,9 +7,16 @@ package org.hibernate.metamodel.model.domain.internal; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.graph.internal.SubGraphImpl; +import org.hibernate.graph.spi.SubGraphImplementor; +import org.hibernate.metamodel.MappingMetamodel; +import org.hibernate.metamodel.mapping.EntityMappingType; +import org.hibernate.metamodel.mapping.MappingModelHelper; import org.hibernate.metamodel.model.domain.EmbeddableDomainType; import org.hibernate.metamodel.model.domain.JpaMetamodel; import org.hibernate.metamodel.model.domain.ManagedDomainType; +import org.hibernate.metamodel.model.domain.PersistentAttribute; +import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; /** * Helper containing utilities useful for domain model handling @@ -24,11 +31,11 @@ public class DomainModelHelper { String subTypeName, JpaMetamodel jpaMetamodel) { if ( baseType instanceof EmbeddableDomainType ) { - // todo : at least validate the string is a valid sub-type of the embeddable class? - return (ManagedDomainType) baseType; + // todo : at least validate the string is a valid subtype of the embeddable class? + return (ManagedDomainType) baseType; } - // first, try to find it by name directly.. + // first, try to find it by name directly ManagedDomainType subManagedType = jpaMetamodel.resolveHqlEntityReference( subTypeName ); if ( subManagedType != null ) { return subManagedType; @@ -36,24 +43,74 @@ public class DomainModelHelper { // it could still be a mapped-superclass try { - final Class javaType = jpaMetamodel.getServiceRegistry() + final Class javaType = jpaMetamodel.getServiceRegistry() .getService( ClassLoaderService.class ) .classForName( subTypeName ); - return jpaMetamodel.managedType( javaType ); + return (ManagedDomainType) jpaMetamodel.managedType( javaType ); } catch (Exception ignore) { } - throw new IllegalArgumentException( "Unknown sub-type name (" + baseType.getTypeName() + ") : " + subTypeName ); + throw new IllegalArgumentException( "Unknown subtype name (" + baseType.getTypeName() + ") : " + subTypeName ); } - public static ManagedDomainType resolveSubType( - ManagedDomainType baseType, - Class subTypeClass, - JpaMetamodel jpaMetamodel) { - // todo : validate the hierarchy-ness... - return jpaMetamodel.managedType( subTypeClass ); + static boolean isCompatible( + PersistentAttribute attribute1, + PersistentAttribute attribute2, + JpaMetamodelImplementor jpaMetamodel) { + if ( attribute1 == attribute2 ) { + return true; + } + final MappingMetamodel mappingMetamodel = jpaMetamodel.getMappingMetamodel(); + final EntityMappingType entity1 = mappingMetamodel.getEntityDescriptor( + attribute1.getDeclaringType().getTypeName() + ); + final EntityMappingType entity2 = mappingMetamodel.getEntityDescriptor( + attribute2.getDeclaringType().getTypeName() + ); + + return entity1 != null && entity2 != null && MappingModelHelper.isCompatibleModelPart( + entity1.findSubPart( attribute1.getName() ), + entity2.findSubPart( attribute2.getName() ) + ); } + public static ManagedDomainType findSubType(ManagedDomainType type, Class subtype) { + if ( type.getBindableJavaType() == subtype ) { + @SuppressWarnings("unchecked") + final ManagedDomainType result = (ManagedDomainType) type; + return result; + } + for ( ManagedDomainType candidate : type.getSubTypes() ) { + if ( candidate.getBindableJavaType() == subtype ) { + @SuppressWarnings("unchecked") + final ManagedDomainType result = (ManagedDomainType) candidate; + return result; + } + } + for ( ManagedDomainType candidate : type.getSubTypes() ) { + final ManagedDomainType candidateSubtype = findSubType( candidate, subtype ); + if ( candidateSubtype != null) { + return candidateSubtype; + } + } + throw new IllegalArgumentException( "The class '" + subtype.getName() + + "' is not a mapped subtype of '" + type.getTypeName() + "'" ); +// return metamodel.managedType( subtype ); + } + public static SubGraphImplementor makeSubGraph(ManagedDomainType type, Class subtype) { + if ( type.getBindableJavaType().isAssignableFrom( subtype ) ) { + return new SubGraphImpl( type, true ); + } + else { + throw new IllegalArgumentException( + String.format( + "Type '%s' cannot be treated as subtype '%s'", + type.getTypeName(), + subtype.getName() + ) + ); + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddableTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddableTypeImpl.java index 6117aa8145..49fadae62d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddableTypeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EmbeddableTypeImpl.java @@ -16,11 +16,10 @@ import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; import org.hibernate.type.descriptor.java.JavaType; /** - * Standard Hibernate implementation of JPA's {@link jakarta.persistence.metamodel.EmbeddableType} - * contract + * Implementation of {@link jakarta.persistence.metamodel.EmbeddableType}. * * @author Emmanuel Bernard - * @author Steve Ebersole` + * @author Steve Ebersole */ public class EmbeddableTypeImpl extends AbstractManagedType @@ -40,10 +39,4 @@ public class EmbeddableTypeImpl public PersistenceType getPersistenceType() { return PersistenceType.EMBEDDABLE; } - - @Override - @SuppressWarnings("unchecked") - public SubGraphImplementor makeSubGraph(Class subType) { - return new SubGraphImpl( this, true ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntitySqmPathSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntitySqmPathSource.java index cec3aaaa48..f7c358bd3d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntitySqmPathSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntitySqmPathSource.java @@ -7,6 +7,7 @@ package org.hibernate.metamodel.model.domain.internal; import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; import org.hibernate.spi.NavigablePath; import org.hibernate.query.hql.spi.SqmCreationState; import org.hibernate.query.sqm.SqmJoinable; @@ -41,8 +42,12 @@ public class EntitySqmPathSource extends AbstractSqmPathSource implements @Override public SqmPathSource findSubPathSource(String name) { - final EntityDomainType sqmPathType = getSqmPathType(); - return sqmPathType.findSubPathSource( name ); + return getSqmPathType().findSubPathSource( name ); + } + + @Override + public SqmPathSource findSubPathSource(String name, JpaMetamodelImplementor metamodel) { + return getSqmPathType().findSubPathSource( name, metamodel ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntityTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntityTypeImpl.java index f6138a6adf..6ee831a1bd 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntityTypeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/EntityTypeImpl.java @@ -9,11 +9,10 @@ package org.hibernate.metamodel.model.domain.internal; import java.io.ObjectStreamException; import java.io.Serializable; import java.util.Collection; +import java.util.Locale; import jakarta.persistence.metamodel.EntityType; -import org.hibernate.graph.internal.SubGraphImpl; -import org.hibernate.graph.spi.SubGraphImplementor; import org.hibernate.mapping.PersistentClass; import org.hibernate.metamodel.UnsupportedMappingException; import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping; @@ -23,18 +22,21 @@ import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.IdentifiableDomainType; import org.hibernate.metamodel.model.domain.JpaMetamodel; +import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.PersistentAttribute; -import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; import org.hibernate.persister.entity.DiscriminatorMetadata; import org.hibernate.persister.entity.Queryable; +import org.hibernate.query.PathException; import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.descriptor.java.JavaType; +import static org.hibernate.metamodel.model.domain.internal.DomainModelHelper.isCompatible; + /** - * Defines the Hibernate implementation of the JPA {@link EntityType} contract. + * Implementation of {@link EntityType}. * * @author Steve Ebersole * @author Emmanuel Bernard @@ -42,7 +44,9 @@ import org.hibernate.type.descriptor.java.JavaType; public class EntityTypeImpl extends AbstractIdentifiableType implements EntityDomainType, Serializable { + private final String jpaEntityName; + private final JpaMetamodelImplementor metamodel; private final SqmPathSource discriminatorPathSource; public EntityTypeImpl( @@ -53,7 +57,7 @@ public class EntityTypeImpl boolean hasVersion, JavaType javaType, IdentifiableDomainType superType, - JpaMetamodelImplementor jpaMetamodel) { + JpaMetamodelImplementor metamodel) { super( entityName, javaType, @@ -61,13 +65,14 @@ public class EntityTypeImpl hasIdClass, hasIdProperty, hasVersion, - jpaMetamodel + metamodel ); this.jpaEntityName = jpaEntityName; + this.metamodel = metamodel; final Queryable entityDescriptor = (Queryable) - jpaMetamodel.getMappingMetamodel() + metamodel.getMappingMetamodel() .getEntityDescriptor( getHibernateEntityName() ); final DiscriminatorMetadata discriminatorMetadata = entityDescriptor.getTypeDiscriminatorMetadata(); final DomainType discriminatorType; @@ -75,7 +80,7 @@ public class EntityTypeImpl discriminatorType = (DomainType) discriminatorMetadata.getResolutionType(); } else { - discriminatorType = jpaMetamodel.getTypeConfiguration() + discriminatorType = metamodel.getTypeConfiguration() .getBasicTypeRegistry() .resolve( StandardBasicTypes.STRING ); } @@ -91,7 +96,7 @@ public class EntityTypeImpl JavaType javaType, IdentifiableDomainType superType, PersistentClass persistentClass, - JpaMetamodelImplementor jpaMetamodel) { + JpaMetamodelImplementor metamodel) { this( persistentClass.getEntityName(), persistentClass.getJpaEntityName(), @@ -101,11 +106,11 @@ public class EntityTypeImpl persistentClass.isVersioned(), javaType, superType, - jpaMetamodel + metamodel ); } - public EntityTypeImpl(JavaType javaTypeDescriptor, JpaMetamodelImplementor jpaMetamodel) { + public EntityTypeImpl(JavaType javaTypeDescriptor, JpaMetamodelImplementor metamodel) { super( javaTypeDescriptor.getJavaTypeClass().getName(), javaTypeDescriptor, @@ -113,10 +118,11 @@ public class EntityTypeImpl false, false, false, - jpaMetamodel + metamodel ); this.jpaEntityName = javaTypeDescriptor.getJavaTypeClass().getName(); + this.metamodel = metamodel; this.discriminatorPathSource = null; } @@ -142,12 +148,12 @@ public class EntityTypeImpl @Override public SqmPathSource findSubPathSource(String name) { - final PersistentAttribute attribute = findAttribute( name ); + final PersistentAttribute attribute = findAttribute( name ); if ( attribute != null ) { return (SqmPathSource) attribute; } - if ( "id".equalsIgnoreCase( name ) ) { + if ( EntityIdentifierMapping.matchesRoleName( name ) ) { if ( hasIdClass() ) { return getIdentifierDescriptor(); } @@ -160,6 +166,52 @@ public class EntityTypeImpl return null; } + @Override + public SqmPathSource findSubPathSource(String name, JpaMetamodelImplementor metamodel) { + final PersistentAttribute attribute = super.findAttribute( name ); + if ( attribute != null ) { + return (SqmPathSource) attribute; + } + + PersistentAttribute subtypeAttribute = findSubtypeAttribute( name, metamodel ); + if ( subtypeAttribute != null ) { + return (SqmPathSource) subtypeAttribute; + } + + if ( EntityIdentifierMapping.matchesRoleName( name ) ) { + return hasIdClass() ? getIdentifierDescriptor() : findIdAttribute(); + } + + if ( EntityDiscriminatorMapping.matchesRoleName( name ) ) { + return discriminatorPathSource; + } + + return null; + } + + private PersistentAttribute findSubtypeAttribute(String name, JpaMetamodelImplementor metamodel) { + PersistentAttribute subtypeAttribute = null; + for ( ManagedDomainType subtype : getSubTypes() ) { + final PersistentAttribute candidate = subtype.findSubTypesAttribute( name ); + if ( candidate != null ) { + if ( subtypeAttribute != null && !isCompatible( subtypeAttribute, candidate, metamodel ) ) { + throw new PathException( + String.format( + Locale.ROOT, + "Could not resolve attribute '%s' of '%s' due to the attribute being declared in multiple subtypes '%s' and '%s'", + name, + getTypeName(), + subtypeAttribute.getDeclaringType().getTypeName(), + candidate.getDeclaringType().getTypeName() + ) + ); + } + subtypeAttribute = candidate; + } + } + return subtypeAttribute; + } + @Override public PersistentAttribute findAttribute(String name) { final PersistentAttribute attribute = super.findAttribute( name ); @@ -167,12 +219,8 @@ public class EntityTypeImpl return attribute; } - if ( "id".equalsIgnoreCase( name ) || EntityIdentifierMapping.ROLE_LOCAL_NAME.equals( name ) ) { - final SingularPersistentAttribute idAttribute = findIdAttribute(); - //noinspection RedundantIfStatement - if ( idAttribute != null ) { - return idAttribute; - } + if ( EntityIdentifierMapping.matchesRoleName( name ) ) { + return findIdAttribute(); } return null; @@ -199,27 +247,6 @@ public class EntityTypeImpl return (Collection>) super.getSubTypes(); } - @Override - @SuppressWarnings("unchecked") - public SubGraphImplementor makeSubGraph(Class subType) { - if ( ! getBindableJavaType().isAssignableFrom( subType ) ) { - throw new IllegalArgumentException( - String.format( - "Entity type [%s] cannot be treated as requested sub-type [%s]", - getName(), - subType.getName() - ) - ); - } - - return new SubGraphImpl( this, true ); - } - - @Override - public SubGraphImplementor makeSubGraph() { - return makeSubGraph( getBindableJavaType() ); - } - @Override public String toString() { return getName(); @@ -236,7 +263,7 @@ public class EntityTypeImpl // Serialization protected Object writeReplace() throws ObjectStreamException { - return new SerialForm( jpaMetamodel(), getHibernateEntityName() ); + return new SerialForm( metamodel, getHibernateEntityName() ); } private static class SerialForm implements Serializable { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java index f27c6e40de..776b5ccc46 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/JpaMetamodelImpl.java @@ -447,7 +447,7 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable { } // create a set of descriptors that should be used to build the polymorphic EntityDomainType - final Set> matchingDescriptors = new HashSet<>(); + final Set> matchingDescriptors = new HashSet<>(); for ( EntityDomainType entityDomainType : jpaEntityTypeMap.values() ) { // see if we should add `entityDomainType` as one of the matching-descriptors. if ( javaType.isAssignableFrom( entityDomainType.getJavaType() ) ) { @@ -477,7 +477,7 @@ public class JpaMetamodelImpl implements JpaMetamodelImplementor, Serializable { } // aside from these special cases, add it - matchingDescriptors.add( entityDomainType ); + matchingDescriptors.add( (EntityDomainType) entityDomainType ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/ListAttributeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/ListAttributeImpl.java index f480a36ae5..be02e1f317 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/ListAttributeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/ListAttributeImpl.java @@ -11,6 +11,7 @@ import java.util.List; import org.hibernate.metamodel.internal.MetadataContext; import org.hibernate.metamodel.mapping.CollectionPart; import org.hibernate.metamodel.model.domain.ListPersistentAttribute; +import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.hql.spi.SqmCreationState; import org.hibernate.query.sqm.internal.SqmMappingModelHelper; @@ -60,6 +61,20 @@ public class ListAttributeImpl extends AbstractPluralAttribute, return getElementPathSource().findSubPathSource( name ); } + @Override + public SqmPathSource findSubPathSource(String name, JpaMetamodelImplementor metamodel) { + final CollectionPart.Nature nature = CollectionPart.Nature.fromNameExact( name ); + if ( nature != null ) { + switch ( nature ) { + case INDEX: + return indexPathSource; + case ELEMENT: + return getElementPathSource(); + } + } + return getElementPathSource().findSubPathSource( name, metamodel ); + } + @Override public SqmPathSource getIntermediatePathSource(SqmPathSource pathSource) { final String pathName = pathSource.getPathName(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MapAttributeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MapAttributeImpl.java index 7fbbb0c168..871046ea70 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MapAttributeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MapAttributeImpl.java @@ -12,6 +12,7 @@ import org.hibernate.metamodel.internal.MetadataContext; import org.hibernate.metamodel.mapping.CollectionPart; import org.hibernate.metamodel.model.domain.MapPersistentAttribute; import org.hibernate.metamodel.model.domain.SimpleDomainType; +import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.hql.spi.SqmCreationState; import org.hibernate.query.sqm.internal.SqmMappingModelHelper; @@ -70,6 +71,20 @@ public class MapAttributeImpl extends AbstractPluralAttribute findSubPathSource(String name, JpaMetamodelImplementor metamodel) { + final CollectionPart.Nature nature = CollectionPart.Nature.fromNameExact( name ); + if ( nature != null ) { + switch ( nature ) { + case INDEX: + return keyPathSource; + case ELEMENT: + return getElementPathSource(); + } + } + return getElementPathSource().findSubPathSource( name, metamodel ); + } + @Override public SqmPathSource getIntermediatePathSource(SqmPathSource pathSource) { final String pathName = pathSource.getPathName(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappedSuperclassTypeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappedSuperclassTypeImpl.java index 22053a7277..c86de0c23d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappedSuperclassTypeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappedSuperclassTypeImpl.java @@ -6,8 +6,6 @@ */ package org.hibernate.metamodel.model.domain.internal; -import org.hibernate.graph.internal.SubGraphImpl; -import org.hibernate.graph.spi.SubGraphImplementor; import org.hibernate.mapping.MappedSuperclass; import org.hibernate.metamodel.UnsupportedMappingException; import org.hibernate.metamodel.mapping.EntityIdentifierMapping; @@ -15,13 +13,14 @@ import org.hibernate.metamodel.model.domain.AbstractIdentifiableType; import org.hibernate.metamodel.model.domain.IdentifiableDomainType; import org.hibernate.metamodel.model.domain.MappedSuperclassDomainType; import org.hibernate.metamodel.model.domain.PersistentAttribute; -import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.type.descriptor.java.JavaType; /** + * Implementation of {@link jakarta.persistence.metamodel.MappedSuperclassType}. + * * @author Emmanuel Bernard * @author Steve Ebersole */ @@ -96,12 +95,8 @@ public class MappedSuperclassTypeImpl extends AbstractIdentifiableType imp return attribute; } - if ( "id".equalsIgnoreCase( name ) || EntityIdentifierMapping.ROLE_LOCAL_NAME.equals( name ) ) { - final SingularPersistentAttribute idAttribute = findIdAttribute(); - //noinspection RedundantIfStatement - if ( idAttribute != null ) { - return idAttribute; - } + if ( EntityIdentifierMapping.matchesRoleName( name ) ) { + return findIdAttribute(); } return null; @@ -117,27 +112,6 @@ public class MappedSuperclassTypeImpl extends AbstractIdentifiableType imp return PersistenceType.MAPPED_SUPERCLASS; } - @Override - @SuppressWarnings("unchecked") - public SubGraphImplementor makeSubGraph(Class subType) { - if ( ! getBindableJavaType().isAssignableFrom( subType ) ) { - throw new IllegalArgumentException( - String.format( - "MappedSuperclass type [%s] cannot be treated as requested sub-type [%s]", - getTypeName(), - subType.getName() - ) - ); - } - - return new SubGraphImpl( this, true ); - } - - @Override - public SubGraphImplementor makeSubGraph() { - return makeSubGraph( getBindableJavaType() ); - } - @Override protected boolean isIdMappingRequired() { return false; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/SingularAttributeImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/SingularAttributeImpl.java index cfc7333d0a..e1b1eecafa 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/SingularAttributeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/SingularAttributeImpl.java @@ -22,6 +22,7 @@ import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; import org.hibernate.metamodel.model.domain.SimpleDomainType; import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; +import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; import org.hibernate.query.SemanticException; import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.hql.spi.SqmCreationState; @@ -130,6 +131,11 @@ public class SingularAttributeImpl return sqmPathSource.findSubPathSource( name ); } + @Override + public SqmPathSource findSubPathSource(String name, JpaMetamodelImplementor metamodel) { + return sqmPathSource.findSubPathSource( name, metamodel ); + } + @Override public SqmPathSource getPathSource() { return this.sqmPathSource; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/package-info.java b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/package-info.java index 8bb803fad5..623e0c0c55 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/package-info.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/package-info.java @@ -16,4 +16,7 @@ * * @see jakarta.persistence.metamodel */ +@Incubating package org.hibernate.metamodel.model.domain; + +import org.hibernate.Incubating; diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 92d5df5842..007ea28416 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -2276,7 +2276,7 @@ public abstract class AbstractEntityPersister //noinspection rawtypes final DiscriminatorConverter converter = MappedDiscriminatorConverter.fromValueMappings( - getNavigableRole().append( EntityDiscriminatorMapping.ROLE_NAME ), + getNavigableRole().append( EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME ), domainJavaType, underlingJdbcMapping, getSubclassByDiscriminatorValue(), @@ -4900,7 +4900,7 @@ public abstract class AbstractEntityPersister } identifierMapping = creationProcess.processSubPart( - EntityIdentifierMapping.ROLE_LOCAL_NAME, + EntityIdentifierMapping.ID_ROLE_NAME, (role, process) -> generateIdentifierMapping( templateInstanceCreator, bootEntityDescriptor, process ) ); @@ -5811,7 +5811,7 @@ public abstract class AbstractEntityPersister } private boolean isIdentifierReference(String name) { - return EntityIdentifierMapping.ROLE_LOCAL_NAME.equals( name ) + return EntityIdentifierMapping.ID_ROLE_NAME.equals( name ) || hasIdentifierProperty() && getIdentifierPropertyName().equals( name ) || !entityMetamodel.hasNonIdentifierPropertyNamedId() && "id".equals( name ); } diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/internal/EntityDomainResultBuilder.java b/hibernate-core/src/main/java/org/hibernate/procedure/internal/EntityDomainResultBuilder.java index 15f7d6bf03..ed02307da3 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/internal/EntityDomainResultBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/procedure/internal/EntityDomainResultBuilder.java @@ -73,7 +73,7 @@ public class EntityDomainResultBuilder implements ResultBuilder { } return discriminatorFetchBuilder.buildFetch( entityResult, - navigablePath.append( EntityDiscriminatorMapping.ROLE_NAME ), + navigablePath.append( EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME ), jdbcResultsMetadata, legacyFetchResolver, domainResultCreationState diff --git a/hibernate-core/src/main/java/org/hibernate/query/derived/AnonymousTupleEntityValuedModelPart.java b/hibernate-core/src/main/java/org/hibernate/query/derived/AnonymousTupleEntityValuedModelPart.java index 8b8dbc0b9d..543bddf501 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/derived/AnonymousTupleEntityValuedModelPart.java +++ b/hibernate-core/src/main/java/org/hibernate/query/derived/AnonymousTupleEntityValuedModelPart.java @@ -100,7 +100,7 @@ public class AnonymousTupleEntityValuedModelPart final EntityPersister persister = ((EntityMappingType) delegate.getPartMappingType()) .getEntityPersister(); final Set targetKeyPropertyNames = new HashSet<>(); - targetKeyPropertyNames.add( EntityIdentifierMapping.ROLE_LOCAL_NAME ); + targetKeyPropertyNames.add( EntityIdentifierMapping.ID_ROLE_NAME ); ToOneAttributeMapping.addPrefixedPropertyNames( targetKeyPropertyNames, persister.getIdentifierPropertyName(), diff --git a/hibernate-core/src/main/java/org/hibernate/query/derived/AnonymousTupleType.java b/hibernate-core/src/main/java/org/hibernate/query/derived/AnonymousTupleType.java index 6b7893401f..f3c21f664d 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/derived/AnonymousTupleType.java +++ b/hibernate-core/src/main/java/org/hibernate/query/derived/AnonymousTupleType.java @@ -117,13 +117,7 @@ public class AnonymousTupleType implements TupleType, DomainType, Retur if ( domainType instanceof EntityDomainType ) { final EntityDomainType entityDomainType = (EntityDomainType) domainType; final SingularPersistentAttribute idAttribute = entityDomainType.findIdAttribute(); - final String idPath; - if ( idAttribute == null ) { - idPath = componentName; - } - else { - idPath = componentName + "_" + idAttribute.getName(); - } + final String idPath = idAttribute == null ? componentName : componentName + "_" + idAttribute.getName(); addColumnNames( columnNames, entityDomainType.getIdentifierDescriptor().getSqmPathType(), idPath ); } else if ( domainType instanceof ManagedDomainType ) { diff --git a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/QualifiedJoinPathConsumer.java b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/QualifiedJoinPathConsumer.java index 6ebb68e217..dfc2fc611e 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/QualifiedJoinPathConsumer.java +++ b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/QualifiedJoinPathConsumer.java @@ -113,38 +113,24 @@ public class QualifiedJoinPathConsumer implements DotIdentifierConsumer { private ConsumerDelegate resolveBase(String identifier, boolean isTerminal) { final SqmCreationProcessingState processingState = creationState.getCurrentProcessingState(); final SqmPathRegistry pathRegistry = processingState.getPathRegistry(); - final SqmFrom pathRootByAlias = pathRegistry.findFromByAlias( identifier, true ); if ( pathRootByAlias != null ) { - // identifier is an alias (identification variable) - - if ( isTerminal ) { - throw new SemanticException( "Cannot join to root entity '" + identifier + "'" ); + return resolveAlias( identifier, isTerminal, pathRootByAlias ); + } + else { + final SqmFrom exposingPathRoot = pathRegistry.findFromExposing( identifier ); + if ( exposingPathRoot != null ) { + return resolveExposed( identifier, isTerminal, exposingPathRoot ); + } + else { + // otherwise, assume we have a qualified entity name + // delay resolution until we process the final token + return resolveEntityName( identifier, isTerminal ); } - - return new AttributeJoinDelegate( - pathRootByAlias, - joinType, - fetch, - alias, - creationState - ); } + } - final SqmFrom pathRootByExposedNavigable = pathRegistry.findFromExposing( identifier ); - if ( pathRootByExposedNavigable != null ) { - return new AttributeJoinDelegate( - createJoin( pathRootByExposedNavigable, identifier, isTerminal ), - joinType, - fetch, - alias, - creationState - ); - } - - // otherwise, assume we have a qualified entity name - delay resolution until we - // process the final token - + private ExpectingEntityJoinDelegate resolveEntityName(String identifier, boolean isTerminal) { return new ExpectingEntityJoinDelegate( identifier, isTerminal, @@ -156,21 +142,43 @@ public class QualifiedJoinPathConsumer implements DotIdentifierConsumer { ); } - private SqmFrom createJoin(SqmFrom lhs, String identifier, boolean isTerminal) { - return createJoin( - lhs, - identifier, + private AttributeJoinDelegate resolveExposed(String identifier, boolean isTerminal, SqmFrom pathRoot) { + return new AttributeJoinDelegate( + createJoin( + pathRoot, + identifier, + joinType, + alias, + fetch, + isTerminal, + true, + creationState + ), joinType, - alias, fetch, - isTerminal, - true, + alias, creationState ); } - private static SqmFrom createJoin( - SqmFrom lhs, + private AttributeJoinDelegate resolveAlias(String identifier, boolean isTerminal, SqmFrom pathRootByAlias) { + // identifier is an alias (identification variable) + if (isTerminal) { + throw new SemanticException( "Cannot join to root entity '" + identifier + "'" ); + } + else { + return new AttributeJoinDelegate( + pathRootByAlias, + joinType, + fetch, + alias, + creationState + ); + } + } + + private static SqmFrom createJoin( + SqmFrom lhs, String name, SqmJoinType joinType, String alias, @@ -178,25 +186,41 @@ public class QualifiedJoinPathConsumer implements DotIdentifierConsumer { boolean isTerminal, boolean allowReuse, SqmCreationState creationState) { - final SqmPathSource referencedPathSource = lhs.getReferencedPathSource(); - // We need to use referencedPathSource when it is not generic since the getResolvedModel() method would - // return the association attribute as a path source and for treated paths that might correspond to a - // different entity type (usually the first in alphabetical order) and not the correct treat target - final SqmPathSource pathSource = referencedPathSource.isGeneric() ? - lhs.getResolvedModel() : - referencedPathSource; - //noinspection unchecked - final SqmPathSource subPathSource = (SqmPathSource) pathSource.getSubPathSource( name ); + final SqmPathSource subPathSource = subPathSource( lhs, name, creationState ); if ( allowReuse && !isTerminal ) { for ( SqmJoin sqmJoin : lhs.getSqmJoins() ) { if ( sqmJoin.getAlias() == null && sqmJoin.getReferencedPathSource() == subPathSource ) { - //noinspection unchecked - return (SqmFrom) sqmJoin; + return sqmJoin; } } } @SuppressWarnings("unchecked") - final SqmJoin join = ( (SqmJoinable) subPathSource ).createSqmJoin( + SqmJoinable joinSource = (SqmJoinable) subPathSource; + return createJoin( lhs, joinType, alias, fetch, isTerminal, allowReuse, creationState, joinSource ); + } + + private static SqmPathSource subPathSource(SqmFrom lhs, String name, SqmCreationState creationState) { + final SqmPathSource referencedPathSource = lhs.getReferencedPathSource(); + // We need to use referencedPathSource when it is not generic since the getResolvedModel() method would + // return the association attribute as a path source and for treated paths that might correspond to a + // different entity type (usually the first in alphabetical order) and not the correct treat target + final SqmPathSource pathSource = + referencedPathSource.isGeneric() + ? lhs.getResolvedModel() + : referencedPathSource; + return pathSource.getSubPathSource( name, creationState.getCreationContext().getJpaMetamodel() ); + } + + private static SqmFrom createJoin( + SqmFrom lhs, + SqmJoinType joinType, + String alias, + boolean fetch, + boolean isTerminal, + boolean allowReuse, + SqmCreationState creationState, + SqmJoinable joinSource) { + final SqmJoin join = joinSource.createSqmJoin( lhs, joinType, isTerminal ? alias : allowReuse ? SqmCreationHelper.IMPLICIT_ALIAS : null, @@ -221,9 +245,9 @@ public class QualifiedJoinPathConsumer implements DotIdentifierConsumer { private final boolean fetch; private final String alias; - private SqmFrom currentPath; + private SqmFrom currentPath; - public AttributeJoinDelegate( + private AttributeJoinDelegate( SqmFrom base, SqmJoinType joinType, boolean fetch, @@ -233,9 +257,7 @@ public class QualifiedJoinPathConsumer implements DotIdentifierConsumer { this.fetch = fetch; this.alias = alias; this.creationState = creationState; - - //noinspection unchecked - this.currentPath = (SqmFrom) base; + this.currentPath = base; } @Override @@ -254,17 +276,16 @@ public class QualifiedJoinPathConsumer implements DotIdentifierConsumer { @Override public void consumeTreat(String entityName, boolean isTerminal) { - final EntityDomainType entityDomainType = creationState.getCreationContext().getJpaMetamodel() - .entity( entityName ); - if ( isTerminal ) { - currentPath = currentPath.treatAs( entityDomainType, alias ); - } - else { - currentPath = currentPath.treatAs( entityDomainType ); - } + currentPath = isTerminal + ? currentPath.treatAs( treatTarget( entityName ), alias) + : currentPath.treatAs( treatTarget( entityName ) ); creationState.getCurrentProcessingState().getPathRegistry().register( currentPath ); } + private EntityDomainType treatTarget(String entityName) { + return creationState.getCreationContext().getJpaMetamodel().entity(entityName); + } + @Override public SemanticPathPart getConsumedPart() { return currentPath; @@ -308,9 +329,9 @@ public class QualifiedJoinPathConsumer implements DotIdentifierConsumer { path.append( identifier ); if ( isTerminal ) { final String fullPath = path.toString(); - final EntityDomainType joinedEntityType = creationState.getCreationContext() - .getJpaMetamodel() - .resolveHqlEntityReference( fullPath ); + final EntityDomainType joinedEntityType = + creationState.getCreationContext().getJpaMetamodel() + .resolveHqlEntityReference( fullPath ); if ( joinedEntityType == null ) { final SqmCteStatement cteStatement = creationState.findCteStatement( fullPath ); if ( cteStatement != null ) { 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 3cac8c2c50..574efbab7e 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 @@ -14,6 +14,7 @@ import java.util.Map; import java.util.function.Function; import org.hibernate.jpa.spi.JpaCompliance; +import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; import org.hibernate.query.hql.HqlLogging; import org.hibernate.query.hql.spi.SqmCreationProcessingState; import org.hibernate.query.hql.spi.SqmPathRegistry; @@ -247,7 +248,11 @@ public class SqmPathRegistryImpl implements SqmPathRegistry { } private boolean definesAttribute(SqmPathSource containerType, String name) { - return containerType.findSubPathSource( name ) != null; + return containerType.findSubPathSource( name, getJpaMetamodel() ) != null; + } + + private JpaMetamodelImplementor getJpaMetamodel() { + return associatedProcessingState.getCreationState().getCreationContext().getJpaMetamodel(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/results/ResultsHelper.java b/hibernate-core/src/main/java/org/hibernate/query/results/ResultsHelper.java index 461c76f5f1..008e73c941 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/results/ResultsHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/query/results/ResultsHelper.java @@ -7,7 +7,6 @@ package org.hibernate.query.results; import org.hibernate.metamodel.mapping.EntityIdentifierMapping; -import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping; @@ -74,11 +73,11 @@ public class ResultsHelper { public static boolean isIdentifier(EntityIdentifierMapping identifierDescriptor, String... names) { final String identifierAttributeName = identifierDescriptor instanceof SingleAttributeIdentifierMapping ? ( (SingleAttributeIdentifierMapping) identifierDescriptor ).getAttributeName() - : EntityIdentifierMapping.ROLE_LOCAL_NAME; + : EntityIdentifierMapping.ID_ROLE_NAME; for ( int i = 0; i < names.length; i++ ) { final String name = names[ i ]; - if ( EntityIdentifierMapping.ROLE_LOCAL_NAME.equals( name ) ) { + if ( EntityIdentifierMapping.ID_ROLE_NAME.equals( name ) ) { return true; } diff --git a/hibernate-core/src/main/java/org/hibernate/query/results/complete/CompleteResultBuilderEntityJpa.java b/hibernate-core/src/main/java/org/hibernate/query/results/complete/CompleteResultBuilderEntityJpa.java index 6d74c5aff8..df162cab09 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/results/complete/CompleteResultBuilderEntityJpa.java +++ b/hibernate-core/src/main/java/org/hibernate/query/results/complete/CompleteResultBuilderEntityJpa.java @@ -122,7 +122,7 @@ public class CompleteResultBuilderEntityJpa implements CompleteResultBuilderEnti return discriminatorFetchBuilder.buildFetch( entityResult, - navigablePath.append( EntityDiscriminatorMapping.ROLE_NAME ), + navigablePath.append( EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME ), jdbcResultsMetadata, legacyFetchResolver, domainResultCreationState diff --git a/hibernate-core/src/main/java/org/hibernate/query/results/complete/CompleteResultBuilderEntityStandard.java b/hibernate-core/src/main/java/org/hibernate/query/results/complete/CompleteResultBuilderEntityStandard.java index 0db6b32679..ab3a9e9571 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/results/complete/CompleteResultBuilderEntityStandard.java +++ b/hibernate-core/src/main/java/org/hibernate/query/results/complete/CompleteResultBuilderEntityStandard.java @@ -156,7 +156,7 @@ public class CompleteResultBuilderEntityStandard implements CompleteResultBuilde return discriminatorFetchBuilder.buildFetch( entityResult, - navigablePath.append( EntityDiscriminatorMapping.ROLE_NAME ), + navigablePath.append( EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME ), jdbcResultsMetadata, legacyFetchResolver, domainResultCreationState diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmPathSource.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmPathSource.java index 86ca66682d..90844b7801 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmPathSource.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/SqmPathSource.java @@ -11,16 +11,18 @@ import java.util.Locale; import jakarta.persistence.metamodel.Bindable; import org.hibernate.metamodel.model.domain.DomainType; +import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; import org.hibernate.spi.NavigablePath; import org.hibernate.query.sqm.tree.SqmExpressibleAccessor; import org.hibernate.query.sqm.tree.domain.SqmPath; /** - * Represents parts of the application's domain model that can be used - * to create {@link SqmPath} nodes. + * Represents any part of the domain model which can be used to create a + * {@link SqmPath} node. * - * @apiNote Parallel to JPA's {@link jakarta.persistence.metamodel.Bindable} but - * broader mainly to support Hibernate ANY-mappings + * @apiNote Parallel to the JPA-defined interface + * {@link jakarta.persistence.metamodel.Bindable} + * but broader mainly to support {@code @Any} mappings * * @author Steve Ebersole */ @@ -38,7 +40,7 @@ public interface SqmPathSource extends SqmExpressible, Bindable, SqmExp DomainType getSqmPathType(); /** - * Find a SqmPathSource by name relative to this source. + * Find a {@link SqmPathSource} by name relative to this source. * * @return null if the subPathSource is not found * @@ -47,7 +49,18 @@ public interface SqmPathSource extends SqmExpressible, Bindable, SqmExp SqmPathSource findSubPathSource(String name); /** - * Find a SqmPathSource by name relative to this source. + * Find a {@link SqmPathSource} by name relative to this source. + * + * @return null if the subPathSource is not found + * + * @throws IllegalStateException to indicate that this source cannot be de-referenced + */ + default SqmPathSource findSubPathSource(String name, JpaMetamodelImplementor metamodel) { + return findSubPathSource( name ); + } + + /** + * Find a {@link SqmPathSource} by name relative to this source. * * @throws IllegalStateException to indicate that this source cannot be de-referenced * @throws IllegalArgumentException if the subPathSource is not found @@ -68,14 +81,36 @@ public interface SqmPathSource extends SqmExpressible, Bindable, SqmExp } /** - * Returns the intermediate SqmPathSource for a path source previously acquired via {@link #findSubPathSource(String)}. + * Find a {@link SqmPathSource} by name relative to this source. + * + * @throws IllegalStateException to indicate that this source cannot be de-referenced + * @throws IllegalArgumentException if the subPathSource is not found + */ + default SqmPathSource getSubPathSource(String name, JpaMetamodelImplementor metamodel) { + final SqmPathSource subPathSource = findSubPathSource( name, metamodel ); + if ( subPathSource == null ) { + throw new PathElementException( + String.format( + Locale.ROOT, + "Could not resolve attribute '%s' of '%s'", + name, + getExpressible().getTypeName() + ) + ); + } + return subPathSource; + } + + /** + * Returns the intermediate {@link SqmPathSource} for a path source + * previously acquired via {@link #findSubPathSource(String)}. */ default SqmPathSource getIntermediatePathSource(SqmPathSource pathSource) { return null; } /** - * Create an SQM path for this source relative to the given left-hand side + * Create an SQM path for this source relative to the given left hand side */ SqmPath createSqmPath(SqmPath lhs, SqmPathSource intermediatePathSource); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/QuerySqmImpl.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/QuerySqmImpl.java index 853ba355c0..c5ea47f1dc 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/QuerySqmImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/QuerySqmImpl.java @@ -838,7 +838,7 @@ public class QuerySqmImpl final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping(); final String partName = identifierMapping instanceof SingleAttributeIdentifierMapping ? identifierMapping.getAttributeName() - : EntityIdentifierMapping.ROLE_LOCAL_NAME; + : EntityIdentifierMapping.ID_ROLE_NAME; for ( SqmPath insertionTargetPath : sqmInsert.getInsertionTargetPaths() ) { final SqmPath lhs = insertionTargetPath.getLhs(); if ( !( lhs instanceof SqmRoot ) ) { 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 b8129fce9e..32af76c59d 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 @@ -5079,7 +5079,7 @@ public abstract class BaseSqmToSqlAstConverter extends Base } final DiscriminatorPathInterpretation typeExpression = new DiscriminatorPathInterpretation<>( - tableGroup.getNavigablePath().append( EntityDiscriminatorMapping.ROLE_NAME ), + tableGroup.getNavigablePath().append( EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME ), entityMapping, tableGroup, this diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmFrom.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmFrom.java index 159667fe87..0148592f21 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmFrom.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/AbstractSqmFrom.java @@ -406,7 +406,8 @@ public abstract class AbstractSqmFrom extends AbstractSqmPath implements @Override @SuppressWarnings("unchecked") public SqmAttributeJoin join(String attributeName, JoinType jt) { - final SqmPathSource subPathSource = getReferencedPathSource().getSubPathSource( attributeName ); + final SqmPathSource subPathSource = + getReferencedPathSource().getSubPathSource( attributeName, nodeBuilder().getJpaMetamodel() ); return (SqmAttributeJoin) buildJoin( subPathSource, SqmJoinType.from( jt ), false ); } @@ -418,7 +419,8 @@ public abstract class AbstractSqmFrom extends AbstractSqmPath implements @Override @SuppressWarnings("unchecked") public SqmBagJoin joinCollection(String attributeName, JoinType jt) { - final SqmPathSource joinedPathSource = getReferencedPathSource().getSubPathSource( attributeName ); + final SqmPathSource joinedPathSource = + getReferencedPathSource().getSubPathSource( attributeName, nodeBuilder().getJpaMetamodel() ); if ( joinedPathSource instanceof BagPersistentAttribute ) { final SqmBagJoin join = buildBagJoin( @@ -449,7 +451,8 @@ public abstract class AbstractSqmFrom extends AbstractSqmPath implements @Override @SuppressWarnings("unchecked") public SqmSetJoin joinSet(String attributeName, JoinType jt) { - final SqmPathSource joinedPathSource = getReferencedPathSource().getSubPathSource( attributeName ); + final SqmPathSource joinedPathSource = + getReferencedPathSource().getSubPathSource( attributeName, nodeBuilder().getJpaMetamodel() ); if ( joinedPathSource instanceof SetPersistentAttribute ) { final SqmSetJoin join = buildSetJoin( @@ -480,7 +483,8 @@ public abstract class AbstractSqmFrom extends AbstractSqmPath implements @Override @SuppressWarnings("unchecked") public SqmListJoin joinList(String attributeName, JoinType jt) { - final SqmPathSource joinedPathSource = getReferencedPathSource().getSubPathSource( attributeName ); + final SqmPathSource joinedPathSource = + getReferencedPathSource().getSubPathSource( attributeName, nodeBuilder().getJpaMetamodel() ); if ( joinedPathSource instanceof ListPersistentAttribute ) { final SqmListJoin join = buildListJoin( @@ -511,7 +515,8 @@ public abstract class AbstractSqmFrom extends AbstractSqmPath implements @Override @SuppressWarnings("unchecked") public SqmMapJoin joinMap(String attributeName, JoinType jt) { - final SqmPathSource joinedPathSource = getReferencedPathSource().getSubPathSource( attributeName ); + final SqmPathSource joinedPathSource = + getReferencedPathSource().getSubPathSource( attributeName, nodeBuilder().getJpaMetamodel() ); if ( joinedPathSource instanceof MapPersistentAttribute ) { final SqmMapJoin join = buildMapJoin( 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 36c8f5fef0..48a25a3455 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 @@ -168,23 +168,24 @@ public abstract class AbstractSqmPath extends AbstractSqmExpression implem @SuppressWarnings("unchecked") public SqmExpression> type() { final SqmPathSource referencedPathSource = getReferencedPathSource(); - final SqmPathSource subPathSource = referencedPathSource.findSubPathSource( EntityDiscriminatorMapping.ROLE_NAME ); + final SqmPathSource subPathSource = referencedPathSource.findSubPathSource( EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME ); if ( subPathSource == null ) { return new SqmLiteral<>( referencedPathSource.getBindableJavaType(), - (SqmExpressible>) (SqmExpressible) nodeBuilder().getTypeConfiguration() - .getBasicTypeForJavaType( Class.class ), + (SqmExpressible>) (SqmExpressible) + nodeBuilder().getTypeConfiguration().getBasicTypeForJavaType( Class.class ), nodeBuilder() ); } - return (SqmExpression>) resolvePath( EntityDiscriminatorMapping.ROLE_NAME, subPathSource ); + return (SqmExpression>) resolvePath( EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME, subPathSource ); } @Override @SuppressWarnings("unchecked") public SqmPath get(String attributeName) { - final SqmPathSource subNavigable = getResolvedModel().getSubPathSource( attributeName ); + final SqmPathSource subNavigable = + getResolvedModel().getSubPathSource( attributeName, nodeBuilder().getSessionFactory().getJpaMetamodel() ); return resolvePath( attributeName, subNavigable ); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPolymorphicRootDescriptor.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPolymorphicRootDescriptor.java index 9f3d12d507..edd807c652 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPolymorphicRootDescriptor.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/domain/SqmPolymorphicRootDescriptor.java @@ -15,7 +15,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Consumer; -import java.util.stream.Collectors; + import jakarta.persistence.metamodel.Attribute; import jakarta.persistence.metamodel.CollectionAttribute; import jakarta.persistence.metamodel.ListAttribute; @@ -24,7 +24,6 @@ import jakarta.persistence.metamodel.PluralAttribute; import jakarta.persistence.metamodel.SetAttribute; import jakarta.persistence.metamodel.SingularAttribute; -import org.hibernate.graph.spi.SubGraphImplementor; import org.hibernate.metamodel.RepresentationMode; import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.EntityDomainType; @@ -37,56 +36,67 @@ import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.type.descriptor.java.JavaType; +import static java.util.Collections.unmodifiableMap; + /** - * Acts as the EntityValuedNavigable for a "polymorphic query" grouping + * Acts as the {@link EntityDomainType} for a "polymorphic query" grouping. * * @author Steve Ebersole */ public class SqmPolymorphicRootDescriptor implements EntityDomainType { - private final Set> implementors; - private final Map commonAttributes; + private final Set> implementors; + private final Map> commonAttributes; private final JavaType polymorphicJavaType; public SqmPolymorphicRootDescriptor( JavaType polymorphicJavaType, - Set> implementors) { + Set> implementors) { this.polymorphicJavaType = polymorphicJavaType; - this.implementors = implementors; + this.commonAttributes = unmodifiableMap( inferCommonAttributes( implementors ) ); + } - final Map workMap = new HashMap<>(); - - final ArrayList> implementorsList = new ArrayList<>( implementors ); - + /** + * The attributes of a "polymorphic" root are the attributes which are + * common to all subtypes of the root type. + */ + private Map> inferCommonAttributes(Set> implementors) { + final Map> workMap = new HashMap<>(); + final ArrayList> implementorsList = new ArrayList<>(implementors); final EntityDomainType firstImplementor = implementorsList.get( 0 ); - if ( implementorsList.size() == 1 ) { firstImplementor.visitAttributes( - attribute -> { - workMap.put( attribute.getName(), attribute ); - } + attribute -> workMap.put( attribute.getName(), promote( attribute ) ) ); } else { - // basically we want to "expose" only the attributes that all the implementors expose... - // - visit all of the attributes defined on the first implementor and check it against - // all of the others + // we want to "expose" only the attributes that all the implementors expose + // visit every attribute declared on the first implementor and check that it + // is also declared by every other implementor final List> subList = implementorsList.subList( 1, implementors.size() - 1 ); firstImplementor.visitAttributes( attribute -> { if ( isACommonAttribute( subList, attribute ) ) { - // if isACommonAttribute - they all had it. so put it in the workMap - // - // todo (6.0) : Atm We use the attribute from the first implementor directly for each implementor - // need to handle this in QuerySplitter somehow - - workMap.put( attribute.getName(), attribute ); + // they all had it, so put it in the workMap + // todo (6.0) : ATM we use the attribute from the first implementor directly for + // each implementor - need to handle this in QuerySplitter somehow + workMap.put( attribute.getName(), promote( attribute ) ); } } ); } - this.commonAttributes = Collections.unmodifiableMap( workMap ); + return workMap; + } + + /** + * Here we pretend that an attribute belonging to all known subtypes + * is an attribute of this type. The unchecked and unsound-looking + * type cast is actually perfectly correct. + */ + @SuppressWarnings("unchecked") + private PersistentAttribute promote(PersistentAttribute attribute) { + return (PersistentAttribute) attribute; } private static boolean isACommonAttribute(List> subList, PersistentAttribute attribute) { @@ -159,12 +169,12 @@ public class SqmPolymorphicRootDescriptor implements EntityDomainType { // Attribute handling @Override - @SuppressWarnings("unchecked") - public PersistentAttribute findAttribute(String name) { + public PersistentAttribute findAttribute(String name) { return commonAttributes.get( name ); } - public PersistentAttribute findSubTypesAttribute(String name) { + @Override + public PersistentAttribute findSubTypesAttribute(String name) { return commonAttributes.get( name ); } @@ -175,8 +185,8 @@ public class SqmPolymorphicRootDescriptor implements EntityDomainType { } @Override - public void visitAttributes(Consumer> action) { - commonAttributes.values().forEach( (Consumer) action ); + public void visitAttributes(Consumer> action) { + commonAttributes.values().forEach( action ); } @Override @@ -200,13 +210,11 @@ public class SqmPolymorphicRootDescriptor implements EntityDomainType { @Override public SingularPersistentAttribute findSingularAttribute(String name) { - //noinspection unchecked return (SingularPersistentAttribute) findAttribute( name ); } @Override public PluralPersistentAttribute findPluralAttribute(String name) { - //noinspection unchecked return (PluralPersistentAttribute) findAttribute( name ); } @@ -221,24 +229,23 @@ public class SqmPolymorphicRootDescriptor implements EntityDomainType { } @Override - public SingularPersistentAttribute findDeclaredSingularAttribute(String name) { + public SingularPersistentAttribute findDeclaredSingularAttribute(String name) { return null; } @Override - public PluralPersistentAttribute findDeclaredPluralAttribute(String name) { + public PluralPersistentAttribute findDeclaredPluralAttribute(String name) { return null; } @Override - public PersistentAttribute findDeclaredConcreteGenericAttribute(String name) { + public PersistentAttribute findDeclaredConcreteGenericAttribute(String name) { return null; } @Override public Set> getAttributes() { - //noinspection unchecked - return (Set>) commonAttributes; + return new HashSet<>( commonAttributes.values() ); } @Override @@ -260,10 +267,13 @@ public class SqmPolymorphicRootDescriptor implements EntityDomainType { @Override public Set> getSingularAttributes() { - //noinspection unchecked - return (Set) commonAttributes.values().stream() - .filter( attribute -> attribute instanceof SingularAttribute ) - .collect( Collectors.toSet() ); + final Set> singularAttributes = new HashSet<>(); + for ( PersistentAttribute attribute : commonAttributes.values() ) { + if ( attribute instanceof SingularAttribute ) { + singularAttributes.add( (SingularPersistentAttribute) attribute ); + } + } + return singularAttributes; } @Override @@ -317,10 +327,13 @@ public class SqmPolymorphicRootDescriptor implements EntityDomainType { @Override public Set> getPluralAttributes() { - //noinspection unchecked - return (Set) commonAttributes.values().stream() - .filter( attribute -> attribute instanceof PluralAttribute ) - .collect( Collectors.toSet() ); + final Set> pluralAttributes = new HashSet<>(); + for ( PersistentAttribute attribute : commonAttributes.values() ) { + if ( attribute instanceof PluralAttribute ) { + pluralAttributes.add( (PluralPersistentAttribute) attribute ); + } + } + return pluralAttributes; } @Override @@ -330,8 +343,7 @@ public class SqmPolymorphicRootDescriptor implements EntityDomainType { @Override public SingularAttribute getSingularAttribute(String name) { - //noinspection unchecked - return (SingularAttribute) getAttribute( name ); + return (SingularPersistentAttribute) getAttribute( name ); } @Override @@ -402,28 +414,6 @@ public class SqmPolymorphicRootDescriptor implements EntityDomainType { return RepresentationMode.POJO; } - @Override - public SubGraphImplementor makeSubGraph() { - throw new UnsupportedOperationException( ); - } - - @Override - public SubGraphImplementor makeSubGraph(Class subType) { - throw new UnsupportedOperationException( ); - } - - @Override - public ManagedDomainType findSubType(String subTypeName) { - // technically we could support this - throw new UnsupportedOperationException( ); - } - - @Override - public ManagedDomainType findSubType(Class type) { - // technically we could support this - throw new UnsupportedOperationException( ); - } - @Override public SqmPathSource getIdentifierDescriptor() { return null; @@ -470,7 +460,7 @@ public class SqmPolymorphicRootDescriptor implements EntityDomainType { } @Override - public SingularPersistentAttribute findIdAttribute() { + public SingularPersistentAttribute findIdAttribute() { throw new UnsupportedOperationException( ); } @@ -509,7 +499,7 @@ public class SqmPolymorphicRootDescriptor implements EntityDomainType { } @Override - public void addSubType(ManagedDomainType subType) { + public void addSubType(ManagedDomainType subType) { throw new UnsupportedOperationException( ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/spi/EntityIdentifierNavigablePath.java b/hibernate-core/src/main/java/org/hibernate/spi/EntityIdentifierNavigablePath.java index 17cecb3632..3a005c0475 100644 --- a/hibernate-core/src/main/java/org/hibernate/spi/EntityIdentifierNavigablePath.java +++ b/hibernate-core/src/main/java/org/hibernate/spi/EntityIdentifierNavigablePath.java @@ -20,12 +20,12 @@ public class EntityIdentifierNavigablePath extends NavigablePath { private final String identifierAttributeName; public EntityIdentifierNavigablePath(NavigablePath parent, String identifierAttributeName) { - super( parent, EntityIdentifierMapping.ROLE_LOCAL_NAME ); + super( parent, EntityIdentifierMapping.ID_ROLE_NAME ); this.identifierAttributeName = identifierAttributeName; } public EntityIdentifierNavigablePath(NavigablePath parent, String alias, String identifierAttributeName) { - super( parent, EntityIdentifierMapping.ROLE_LOCAL_NAME, alias ); + super( parent, EntityIdentifierMapping.ID_ROLE_NAME, alias ); this.identifierAttributeName = identifierAttributeName; } @@ -35,7 +35,7 @@ public class EntityIdentifierNavigablePath extends NavigablePath { @Override public String getLocalName() { - return EntityIdentifierMapping.ROLE_LOCAL_NAME; + return EntityIdentifierMapping.ID_ROLE_NAME; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/DomainResultCreationState.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/DomainResultCreationState.java index 07aa81158d..625bc22b8a 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/DomainResultCreationState.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/DomainResultCreationState.java @@ -6,17 +6,12 @@ */ package org.hibernate.sql.results.graph; -import java.util.List; - import org.hibernate.Incubating; import org.hibernate.engine.FetchTiming; import org.hibernate.metamodel.mapping.AssociationKey; -import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; -import org.hibernate.metamodel.mapping.EntityAssociationMapping; import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityMappingType; -import org.hibernate.metamodel.mapping.EntityValuedModelPart; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.spi.EntityIdentifierNavigablePath; @@ -110,7 +105,7 @@ public interface DomainResultCreationState { if ( discriminatorMapping != null && entityDescriptor.hasSubclasses() ) { return discriminatorMapping.generateFetch( fetchParent, - fetchParent.getNavigablePath().append( EntityDiscriminatorMapping.ROLE_NAME ), + fetchParent.getNavigablePath().append( EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME ), FetchTiming.IMMEDIATE, true, null, 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 4bf012d9fc..ec5ea86562 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 @@ -91,7 +91,7 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA private static boolean isPartOfKey(NavigableRole navigableRole) { final NavigableRole parent = navigableRole.getParent(); return parent != null - && ( parent.getLocalName().equals( EntityIdentifierMapping.ROLE_LOCAL_NAME ) || isPartOfKey( parent ) ); + && ( parent.getLocalName().equals( EntityIdentifierMapping.ID_ROLE_NAME ) || isPartOfKey( parent ) ); } protected DomainResultAssembler[] createAssemblers( diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedResultImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedResultImpl.java index c195862f52..81e06c5c12 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedResultImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedResultImpl.java @@ -8,7 +8,6 @@ package org.hibernate.sql.results.graph.entity.internal; import org.hibernate.metamodel.mapping.EntityAssociationMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping; -import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.ast.tree.from.TableGroup; @@ -39,7 +38,7 @@ public class EntityDelayedResultImpl implements DomainResult { this.navigablePath = navigablePath; this.entityValuedModelPart = entityValuedModelPart; this.identifierResult = entityValuedModelPart.getForeignKeyDescriptor().createKeyDomainResult( - navigablePath.append( EntityIdentifierMapping.ROLE_LOCAL_NAME ), + navigablePath.append( EntityIdentifierMapping.ID_ROLE_NAME ), targetTableGroup, entityValuedModelPart.getSideNature(), null, diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/binding/hbm/simple/dynamic/SimpleDynamicHbmTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/binding/hbm/simple/dynamic/SimpleDynamicHbmTests.java index b4fab199d1..87397d7f45 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/binding/hbm/simple/dynamic/SimpleDynamicHbmTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/binding/hbm/simple/dynamic/SimpleDynamicHbmTests.java @@ -47,7 +47,7 @@ public class SimpleDynamicHbmTests { assertThat( identifierMapping, instanceOf( BasicEntityIdentifierMapping.class ) ); final BasicEntityIdentifierMapping bid = (BasicEntityIdentifierMapping) identifierMapping; assertThat( bid.getFetchableName(), is( "id" ) ); - assertThat( bid.getPartName(), is( EntityIdentifierMapping.ROLE_LOCAL_NAME ) ); + assertThat( bid.getPartName(), is( EntityIdentifierMapping.ID_ROLE_NAME ) ); assertThat( entityDescriptor.getNumberOfAttributeMappings(), is( 1 ) ); assertThat( entityDescriptor.getNumberOfDeclaredAttributeMappings(), is( 1 ) ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/binding/hbm/simple/pojo/SimpleHbmTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/binding/hbm/simple/pojo/SimpleHbmTests.java index 47903a3682..9fb102a5c2 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/binding/hbm/simple/pojo/SimpleHbmTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/binding/hbm/simple/pojo/SimpleHbmTests.java @@ -42,7 +42,7 @@ public class SimpleHbmTests { assertThat( identifierMapping, instanceOf( BasicEntityIdentifierMapping.class ) ); final BasicEntityIdentifierMapping bid = (BasicEntityIdentifierMapping) identifierMapping; assertThat( bid.getFetchableName(), is( "id" ) ); - assertThat( bid.getPartName(), is( EntityIdentifierMapping.ROLE_LOCAL_NAME ) ); + assertThat( bid.getPartName(), is( EntityIdentifierMapping.ID_ROLE_NAME ) ); assertThat( entityDescriptor.getNumberOfAttributeMappings(), is( 1 ) ); assertThat( entityDescriptor.getNumberOfDeclaredAttributeMappings(), is( 1 ) ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/AttributePathTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/AttributePathTests.java index fbbdc351a7..1f0960e390 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/AttributePathTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/AttributePathTests.java @@ -111,7 +111,7 @@ public class AttributePathTests extends BaseSqmUnitTest { final EntityDomainType entity = sessionFactory().getRuntimeMetamodels() .getJpaMetamodel() .entity( OddOne.class ); - final SingularPersistentAttribute idAttribute = entity.findIdAttribute(); + final SingularPersistentAttribute idAttribute = entity.findIdAttribute(); final SqmSelectStatement sqmSelectStatement = interpretSelect( "select s.id from OddOne s where s.pk = ?1" ); 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 index 6574b2d39a..8aede50abe 100644 --- 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 @@ -103,12 +103,12 @@ public class NavigablePathTests { final String aliasedRootStr = "org.hibernate.Root(r)"; final String pkStr = "pk"; - final String pkFullPathStr = aliasedRootStr + "." + EntityIdentifierMapping.ROLE_LOCAL_NAME; + final String pkFullPathStr = aliasedRootStr + "." + EntityIdentifierMapping.ID_ROLE_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.getLocalName() ).isEqualTo( EntityIdentifierMapping.ID_ROLE_NAME ); assertThat( idPath.getFullPath() ).isEqualTo( pkFullPathStr ); } }