From 2e0b4b3558bb656ad54d1c47a6fc4d3c82f5a148 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Thu, 15 Dec 2022 12:29:17 -0600 Subject: [PATCH] HHH-15883 - Expose MappingMetamodel via unwrap from SessionFactory HHH-15884 - Clean-up EntityDiscriminatorMapping for API uses --- .../engine/spi/LoadQueryInfluencers.java | 11 ++- .../internal/SessionFactoryImpl.java | 47 ++++------- .../hibernate/loader/ast/spi/Loadable.java | 32 ++++++-- .../mapping/EntityDiscriminatorMapping.java | 49 +++++++++-- .../AbstractDiscriminatorMapping.java | 82 ++++++++++++------- ...CaseStatementDiscriminatorMappingImpl.java | 3 +- ...xplicitColumnDiscriminatorMappingImpl.java | 11 ++- .../entity/AbstractEntityPersister.java | 12 ++- .../persister/entity/DiscriminatorHelper.java | 36 ++++---- .../persister/entity/DiscriminatorType.java | 18 ++-- .../entity/DiscriminatorValueDetailsImpl.java | 40 +++++++++ .../persister/entity/EntityPersister.java | 4 +- .../entity/JoinedSubclassEntityPersister.java | 29 +++++++ .../hibernate/persister/entity/Loadable.java | 17 ++++ .../hibernate/persister/entity/Queryable.java | 12 +++ .../entity/SingleTableEntityPersister.java | 35 +++++++- .../entity/UnionSubclassEntityPersister.java | 25 ++++++ .../sql/results/graph/Fetchable.java | 6 +- .../entity/AbstractEntityInitializer.java | 30 +++---- 19 files changed, 370 insertions(+), 129 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorValueDetailsImpl.java diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/LoadQueryInfluencers.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/LoadQueryInfluencers.java index ddaaa3c26e..50a79c9bdb 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/LoadQueryInfluencers.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/LoadQueryInfluencers.java @@ -83,13 +83,22 @@ public class LoadQueryInfluencers implements Serializable { } } + /** + * Fetch-profile to apply, if one, when building the result-graph + * for cascade fetching - for example, the result-graph used when + * handling a {@linkplain org.hibernate.Session#merge merge} to + * immediately load additional based on {@linkplain jakarta.persistence.CascadeType#MERGE} + */ public CascadingFetchProfile getEnabledCascadingFetchProfile() { return enabledCascadingFetchProfile; } + /** + * Set the effective {@linkplain #getEnabledCascadingFetchProfile() cascading fetch-profile} + */ public void setEnabledCascadingFetchProfile(CascadingFetchProfile enabledCascadingFetchProfile) { if ( sessionFactory == null ) { - // thats the signal that this is the immutable, context-less + // that's the signal that this is the immutable, context-less // variety throw new IllegalStateException( "Cannot modify context-less LoadQueryInfluencers" ); } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java index e49882f7f7..6454ef7c1a 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java @@ -25,14 +25,6 @@ import java.util.function.Supplier; import javax.naming.Reference; import javax.naming.StringRefAddr; -import jakarta.persistence.Cache; -import jakarta.persistence.EntityGraph; -import jakarta.persistence.EntityManagerFactory; -import jakarta.persistence.PersistenceException; -import jakarta.persistence.PersistenceUnitUtil; -import jakarta.persistence.Query; -import jakarta.persistence.SynchronizationType; - import org.hibernate.CustomEntityDirtinessStrategy; import org.hibernate.EntityNameResolver; import org.hibernate.FlushMode; @@ -64,7 +56,6 @@ import org.hibernate.context.internal.ManagedSessionContext; import org.hibernate.context.internal.ThreadLocalSessionContext; import org.hibernate.context.spi.CurrentSessionContext; import org.hibernate.context.spi.CurrentTenantIdentifierResolver; -import org.hibernate.dialect.Dialect; import org.hibernate.engine.config.spi.ConfigurationService; import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess; import org.hibernate.engine.jdbc.spi.JdbcServices; @@ -78,6 +69,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform; import org.hibernate.event.spi.EventEngine; +import org.hibernate.generator.Generator; import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.factory.IdentifierGeneratorFactory; @@ -91,11 +83,10 @@ import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.RootClass; import org.hibernate.metadata.CollectionMetadata; import org.hibernate.metamodel.internal.RuntimeMetamodelsImpl; -import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; -import org.hibernate.metamodel.spi.RuntimeMetamodelsImplementor; -import org.hibernate.query.BindableType; import org.hibernate.metamodel.model.domain.internal.MappingMetamodelImpl; +import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor; import org.hibernate.metamodel.spi.MetamodelImplementor; +import org.hibernate.metamodel.spi.RuntimeMetamodelsImplementor; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.Loadable; import org.hibernate.persister.entity.SessionFactoryBasedWrapperOptions; @@ -103,6 +94,7 @@ import org.hibernate.procedure.spi.ProcedureCallImplementor; import org.hibernate.proxy.EntityNotFoundDelegate; import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.LazyInitializer; +import org.hibernate.query.BindableType; import org.hibernate.query.QueryLogging; import org.hibernate.query.hql.spi.SqmQueryImplementor; import org.hibernate.query.named.NamedObjectRepository; @@ -124,13 +116,18 @@ import org.hibernate.service.spi.SessionFactoryServiceRegistryFactory; import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.tool.schema.spi.DelayedDropAction; import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator; -import org.hibernate.generator.Generator; import org.hibernate.type.Type; import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.spi.TypeConfiguration; import org.jboss.logging.Logger; +import jakarta.persistence.EntityGraph; +import jakarta.persistence.PersistenceException; +import jakarta.persistence.PersistenceUnitUtil; +import jakarta.persistence.Query; +import jakarta.persistence.SynchronizationType; + import static java.util.Collections.unmodifiableSet; /** @@ -901,31 +898,19 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { @Override public T unwrap(Class type) { - if ( type.isAssignableFrom( SessionFactory.class ) ) { + if ( type.isInstance( this ) ) { return type.cast( this ); } - if ( type.isAssignableFrom( SessionFactoryImplementor.class ) ) { - return type.cast( this ); - } - - if ( type.isAssignableFrom( SessionFactoryImpl.class ) ) { - return type.cast( this ); - } - - if ( type.isAssignableFrom( EntityManagerFactory.class ) ) { - return type.cast( this ); - } - - if ( type.isAssignableFrom( SessionFactoryServiceRegistry.class ) ) { + if ( type.isInstance( serviceRegistry ) ) { return type.cast( serviceRegistry ); } - if ( type.isAssignableFrom( JdbcServices.class ) ) { + if ( type.isInstance( jdbcServices ) ) { return type.cast( jdbcServices ); } - if ( type.isAssignableFrom( Cache.class ) || type.isAssignableFrom( org.hibernate.Cache.class ) ) { + if ( type.isInstance( cacheAccess ) ) { return type.cast( cacheAccess ); } @@ -937,11 +922,11 @@ public class SessionFactoryImpl implements SessionFactoryImplementor { return type.cast( runtimeMetamodels.getJpaMetamodel() ); } - if ( type.isAssignableFrom( MetamodelImplementor.class ) || type.isAssignableFrom( MetadataImplementor.class ) ) { + if ( type.isInstance( runtimeMetamodels.getMappingMetamodel() ) ) { return type.cast( runtimeMetamodels.getMappingMetamodel() ); } - if ( type.isAssignableFrom( QueryEngine.class ) ) { + if ( type.isInstance( queryEngine ) ) { return type.cast( queryEngine ); } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/spi/Loadable.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/spi/Loadable.java index b07ba35bd8..b1d01509d9 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/spi/Loadable.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/spi/Loadable.java @@ -11,19 +11,37 @@ import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.sql.ast.tree.from.RootTableGroupProducer; /** - * Contract for things that can be loaded by a Loader. - * - * Generally speaking this is limited to entities and collections + * Common details for things that can be loaded by a {@linkplain Loader loader} - generally + * {@linkplain org.hibernate.metamodel.mapping.EntityMappingType entities} and + * {@linkplain org.hibernate.metamodel.mapping.PluralAttributeMapping plural attributes} (collections). * * @see Loader + * @see org.hibernate.metamodel.mapping.EntityMappingType + * @see org.hibernate.metamodel.mapping.PluralAttributeMapping * * @author Steve Ebersole */ public interface Loadable extends ModelPart, RootTableGroupProducer { - boolean isAffectedByEnabledFilters(LoadQueryInfluencers influencers); - boolean isAffectedByEntityGraph(LoadQueryInfluencers influencers); - boolean isAffectedByEnabledFetchProfiles(LoadQueryInfluencers influencers); - + /** + * The name for this loadable, for use as the root when generating + * {@linkplain org.hibernate.spi.NavigablePath relative paths} + */ String getRootPathName(); + /** + * Whether any of the "influencers" affect this loadable. + */ + boolean isAffectedByEnabledFilters(LoadQueryInfluencers influencers); + + /** + * Whether the {@linkplain LoadQueryInfluencers#getEffectiveEntityGraph() effective entity-graph} + * applies to this loadable + */ + boolean isAffectedByEntityGraph(LoadQueryInfluencers influencers); + + /** + * Whether any of the {@linkplain LoadQueryInfluencers#getEnabledFetchProfileNames()} + * apply to this loadable + */ + boolean isAffectedByEnabledFetchProfiles(LoadQueryInfluencers influencers); } 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 d44bb799d4..fb5951cf79 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 @@ -8,7 +8,6 @@ package org.hibernate.metamodel.mapping; import org.hibernate.engine.FetchStyle; import org.hibernate.engine.FetchTiming; -import org.hibernate.persister.entity.DiscriminatorType; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.ast.spi.SqlAstCreationState; import org.hibernate.sql.ast.tree.expression.Expression; @@ -19,6 +18,11 @@ import org.hibernate.sql.results.graph.FetchParent; import org.hibernate.sql.results.graph.basic.BasicFetch; /** + * Details about the discriminator for an entity hierarchy. + * + * @implNote All {@linkplain EntityMappingType entity-mappings} within the + * hierarchy share the same EntityDiscriminatorMapping instance. + * * @see jakarta.persistence.DiscriminatorColumn * @see jakarta.persistence.DiscriminatorValue * @@ -42,16 +46,51 @@ public interface EntityDiscriminatorMapping extends VirtualModelPart, BasicValue return getPartName(); } + /** + * Is the discriminator defined by a physical column? + */ + boolean isPhysical(); + @Override default int getFetchableKey() { return -2; } - DiscriminatorType getDiscriminatorType(); + /** + * Retrieve the details for a particular discriminator value. + * + * Returns {@code null} if there is no match. + */ + DiscriminatorValueDetails resolveDiscriminatorValue(Object value); - String getConcreteEntityNameForDiscriminatorValue(Object value); + /** + * Details for a particular discriminator value. + * + * @apiNote For {@linkplain jakarta.persistence.InheritanceType#JOINED joined} + * {@linkplain jakarta.persistence.InheritanceType#TABLE_PER_CLASS union} inheritance, + * the discriminator also effectively indicates a specific table. That table can be + * found via {@linkplain EntityMappingType#getMappedTableDetails()} for the + * {@linkplain #getIndicatedEntity() indicated entity} + * + * @see jakarta.persistence.DiscriminatorValue + */ + interface DiscriminatorValueDetails { + /** + * The discriminator value + */ + Object getValue(); - boolean isPhysical(); + /** + * The SQL literal representation of the discriminator value. E.g. + * for Strings, this would be the fully SQL-quoted form. + */ + Object getSqlLiteralValue(); + + /** + * The concrete entity-type mapped to this discriminator value + */ + EntityMappingType getIndicatedEntity(); + } /** * Create the appropriate SQL expression for this discriminator @@ -66,7 +105,7 @@ public interface EntityDiscriminatorMapping extends VirtualModelPart, BasicValue SqlAstCreationState creationState); @Override - BasicFetch generateFetch( + BasicFetch generateFetch( FetchParent fetchParent, NavigablePath fetchablePath, FetchTiming fetchTiming, 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 dcf036a518..ac81ec2dc9 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 @@ -6,10 +6,10 @@ */ package org.hibernate.metamodel.mapping.internal; +import java.util.Map; import java.util.function.BiConsumer; import org.hibernate.engine.FetchTiming; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.mapping.IndexedConsumer; import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping; @@ -19,7 +19,6 @@ import org.hibernate.metamodel.mapping.MappingType; import org.hibernate.metamodel.mapping.SelectableConsumer; import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.persister.entity.DiscriminatorType; -import org.hibernate.persister.entity.EntityPersister; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.ast.spi.SqlAstCreationState; import org.hibernate.sql.ast.spi.SqlExpressionResolver; @@ -33,6 +32,9 @@ import org.hibernate.sql.results.graph.basic.BasicResult; import org.hibernate.type.BasicType; import org.hibernate.type.descriptor.java.JavaType; +import static org.hibernate.persister.entity.DiscriminatorHelper.NOT_NULL_DISCRIMINATOR; +import static org.hibernate.persister.entity.DiscriminatorHelper.NULL_DISCRIMINATOR; + /** * @implNote `discriminatorType` represents the mapping to Class, whereas `discriminatorType.getUnderlyingType()` * represents the "raw" JDBC mapping (String, Integer, etc) @@ -42,38 +44,36 @@ import org.hibernate.type.descriptor.java.JavaType; public abstract class AbstractDiscriminatorMapping implements EntityDiscriminatorMapping { private final NavigableRole role; - private final EntityPersister entityDescriptor; - private final DiscriminatorType discriminatorType; - private final SessionFactoryImplementor sessionFactory; + private final JdbcMapping jdbcMapping; + + private final EntityMappingType entityDescriptor; + private final Map valueMappings; + + private final DiscriminatorType discriminatorType; public AbstractDiscriminatorMapping( - EntityPersister entityDescriptor, + EntityMappingType entityDescriptor, DiscriminatorType discriminatorType, + Map valueMappings, MappingModelCreationProcess creationProcess) { + this.jdbcMapping = discriminatorType.getUnderlyingType().getJdbcMapping(); this.entityDescriptor = entityDescriptor; - this.discriminatorType = discriminatorType; + this.valueMappings = valueMappings; - role = entityDescriptor.getNavigableRole().append( EntityDiscriminatorMapping.ROLE_NAME ); - sessionFactory = creationProcess.getCreationContext().getSessionFactory(); + this.role = entityDescriptor.getNavigableRole().append( EntityDiscriminatorMapping.ROLE_NAME ); + + //noinspection unchecked + this.discriminatorType = (DiscriminatorType) discriminatorType; } - public EntityPersister getEntityDescriptor() { + public EntityMappingType getEntityDescriptor() { return entityDescriptor; } - @Override - public DiscriminatorType getDiscriminatorType() { - return discriminatorType; - } - public BasicType getUnderlyingJdbcMappingType() { return discriminatorType.getUnderlyingType(); } - public SessionFactoryImplementor getSessionFactory() { - return sessionFactory; - } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // EntityDiscriminatorMapping @@ -89,8 +89,17 @@ public abstract class AbstractDiscriminatorMapping implements EntityDiscriminato } @Override - public String getConcreteEntityNameForDiscriminatorValue(Object value) { - return getEntityDescriptor().getSubclassForDiscriminatorValue( value ); + public DiscriminatorValueDetails resolveDiscriminatorValue(Object value) { + if ( value == null ) { + return valueMappings.get( NULL_DISCRIMINATOR ); + } + + final DiscriminatorValueDetails matchedType = valueMappings.get( value ); + if ( matchedType != null ) { + return matchedType; + } + + return valueMappings.get( NOT_NULL_DISCRIMINATOR ); } @Override @@ -108,24 +117,28 @@ public abstract class AbstractDiscriminatorMapping implements EntityDiscriminato return getJdbcMapping().getJavaTypeDescriptor(); } + @SuppressWarnings({ "rawtypes", "unchecked" }) @Override - public DomainResult createDomainResult( + public DomainResult createDomainResult( NavigablePath navigablePath, TableGroup tableGroup, String resultVariable, DomainResultCreationState creationState) { + // create a SqlSelection based on the underlying JdbcMapping final SqlSelection sqlSelection = resolveSqlSelection( navigablePath, - getUnderlyingJdbcMappingType(), + jdbcMapping, tableGroup, null, creationState.getSqlAstCreationState() ); - return new BasicResult<>( + // return a BasicResult with conversion the entity class or entity-name + return new BasicResult( sqlSelection.getValuesArrayPosition(), resultVariable, - discriminatorType, + discriminatorType.getJavaTypeDescriptor(), + discriminatorType.getValueConverter(), navigablePath ); } @@ -160,19 +173,22 @@ public abstract class AbstractDiscriminatorMapping implements EntityDiscriminato assert tableGroup != null; + // create a SqlSelection based on the underlying JdbcMapping final SqlSelection sqlSelection = resolveSqlSelection( fetchablePath, - getUnderlyingJdbcMappingType(), + jdbcMapping, tableGroup, fetchParent, creationState.getSqlAstCreationState() ); + // return a BasicFetch with conversion the entity class or entity-name return new BasicFetch<>( sqlSelection.getValuesArrayPosition(), fetchParent, fetchablePath, this, + discriminatorType.getValueConverter(), fetchTiming, creationState ); @@ -183,7 +199,13 @@ public abstract class AbstractDiscriminatorMapping implements EntityDiscriminato NavigablePath navigablePath, TableGroup tableGroup, DomainResultCreationState creationState) { - resolveSqlSelection( navigablePath, getUnderlyingJdbcMappingType(), tableGroup, null, creationState.getSqlAstCreationState() ); + resolveSqlSelection( + navigablePath, + jdbcMapping, + tableGroup, + null, + creationState.getSqlAstCreationState() + ); } @Override @@ -193,7 +215,7 @@ public abstract class AbstractDiscriminatorMapping implements EntityDiscriminato DomainResultCreationState creationState, BiConsumer selectionConsumer) { selectionConsumer.accept( - resolveSqlSelection( navigablePath, getUnderlyingJdbcMappingType(), tableGroup, null, creationState.getSqlAstCreationState() ), + resolveSqlSelection( navigablePath, jdbcMapping, tableGroup, null, creationState.getSqlAstCreationState() ), getJdbcMapping() ); } @@ -204,13 +226,13 @@ public abstract class AbstractDiscriminatorMapping implements EntityDiscriminato int offset, JdbcValuesConsumer valuesConsumer, SharedSessionContractImplementor session) { - valuesConsumer.consume( offset, value, getJdbcMapping() ); + valuesConsumer.consume( offset, value, jdbcMapping ); return getJdbcTypeCount(); } @Override public int forEachJdbcType(int offset, IndexedConsumer action) { - action.accept( offset, getJdbcMapping() ); + action.accept( offset, jdbcMapping ); return getJdbcTypeCount(); } 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 309542be58..cd411f013c 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 @@ -50,8 +50,9 @@ public class CaseStatementDiscriminatorMappingImpl extends AbstractDiscriminator String[] discriminatorValues, Map subEntityNameByTableName, DiscriminatorType incomingDiscriminatorType, + Map valueMappings, MappingModelCreationProcess creationProcess) { - super( entityDescriptor, incomingDiscriminatorType, creationProcess ); + super( entityDescriptor, incomingDiscriminatorType, valueMappings, creationProcess ); for ( int i = 0; i < discriminatorValues.length; i++ ) { final String tableName = tableNames[notNullColumnTableNumbers[i]]; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ExplicitColumnDiscriminatorMappingImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ExplicitColumnDiscriminatorMappingImpl.java index c64e623397..68ba3347d5 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ExplicitColumnDiscriminatorMappingImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ExplicitColumnDiscriminatorMappingImpl.java @@ -6,9 +6,11 @@ */ package org.hibernate.metamodel.mapping.internal; +import java.util.Map; + +import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.persister.entity.DiscriminatorType; -import org.hibernate.persister.entity.EntityPersister; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.ast.spi.SqlAstCreationState; import org.hibernate.sql.ast.spi.SqlExpressionResolver; @@ -30,8 +32,7 @@ public class ExplicitColumnDiscriminatorMappingImpl extends AbstractDiscriminato private final Integer scale; public ExplicitColumnDiscriminatorMappingImpl( - EntityPersister entityDescriptor, - DiscriminatorType discriminatorType, + EntityMappingType entityDescriptor, String tableExpression, String columnExpression, boolean isFormula, @@ -40,8 +41,10 @@ public class ExplicitColumnDiscriminatorMappingImpl extends AbstractDiscriminato Long length, Integer precision, Integer scale, + DiscriminatorType discriminatorType, + Map valueMappings, MappingModelCreationProcess creationProcess) { - super( entityDescriptor, discriminatorType, creationProcess ); + super( entityDescriptor, discriminatorType, valueMappings, creationProcess ); this.tableExpression = tableExpression; this.isPhysical = isPhysical; this.columnDefinition = columnDefinition; 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 2906df180f..7dff3022b9 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 @@ -161,6 +161,7 @@ import org.hibernate.metamodel.mapping.BasicValuedModelPart; import org.hibernate.metamodel.mapping.DiscriminatedAssociationModelPart; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping; +import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping.DiscriminatorValueDetails; import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityRowIdMapping; @@ -4992,16 +4993,23 @@ public abstract class AbstractEntityPersister } return new ExplicitColumnDiscriminatorMappingImpl ( this, - (DiscriminatorType) getTypeDiscriminatorMetadata().getResolutionType(), getTableName(), discriminatorColumnExpression, getDiscriminatorFormulaTemplate() != null, isPhysicalDiscriminator(), - columnDefinition, length, precision, scale, modelCreationProcess + columnDefinition, length, precision, scale, + (DiscriminatorType) getTypeDiscriminatorMetadata().getResolutionType(), + buildDiscriminatorValueMappings( bootEntityDescriptor, modelCreationProcess ), + modelCreationProcess ); } } + protected abstract Map buildDiscriminatorValueMappings( + PersistentClass bootEntityDescriptor, + MappingModelCreationProcess modelCreationProcess); + + protected EntityVersionMapping generateVersionMapping( Supplier templateInstanceCreator, PersistentClass bootEntityDescriptor, diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorHelper.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorHelper.java index 6ef95e840e..932d9ce6bc 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorHelper.java @@ -6,6 +6,7 @@ */ package org.hibernate.persister.entity; +import org.hibernate.Internal; import org.hibernate.MappingException; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionFactoryImplementor; @@ -14,18 +15,18 @@ import org.hibernate.mapping.PersistentClass; import org.hibernate.sql.InFragment; import org.hibernate.type.BasicType; import org.hibernate.type.Type; -import org.hibernate.type.descriptor.WrapperOptions; -import org.hibernate.type.descriptor.java.JavaType; +import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter; /** * Operations needed by persisters for working with discriminators. * * @author Gavin King */ -class DiscriminatorHelper { +@Internal +public class DiscriminatorHelper { - static final Object NULL_DISCRIMINATOR = new MarkerObject( "" ); - static final Object NOT_NULL_DISCRIMINATOR = new MarkerObject( "" ); + public static final Object NULL_DISCRIMINATOR = new MarkerObject( "" ); + public static final Object NOT_NULL_DISCRIMINATOR = new MarkerObject( "" ); static BasicType getDiscriminatorType(PersistentClass persistentClass) { Type discriminatorType = persistentClass.getDiscriminator().getType(); @@ -51,8 +52,7 @@ class DiscriminatorHelper { return discriminatorSqlLiteral( getDiscriminatorType( persistentClass ), persistentClass, - dialect, - factory.getWrapperOptions() + dialect ); } } @@ -82,16 +82,20 @@ class DiscriminatorHelper { private static String discriminatorSqlLiteral( BasicType discriminatorType, PersistentClass persistentClass, - Dialect dialect, - WrapperOptions wrapperOptions) { - final JavaType javaType = discriminatorType.getJavaTypeDescriptor(); + Dialect dialect) { + return jdbcLiteral( + discriminatorType.getJavaTypeDescriptor().fromString( persistentClass.getDiscriminatorValue() ), + discriminatorType.getJdbcLiteralFormatter(), + dialect + ); + } + + public static String jdbcLiteral( + T value, + JdbcLiteralFormatter formatter, + Dialect dialect) { try { - return discriminatorType.getJdbcLiteralFormatter() - .toJdbcLiteral( - javaType.fromString( persistentClass.getDiscriminatorValue() ), - dialect, - wrapperOptions - ); + return formatter.toJdbcLiteral( value, dialect, null ); } catch (Exception e) { throw new MappingException( "Could not format discriminator value to SQL string", e ); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorType.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorType.java index e0846fb58a..f92703a367 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorType.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorType.java @@ -19,6 +19,8 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.metamodel.RepresentationMode; +import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping.DiscriminatorValueDetails; +import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.model.convert.spi.BasicValueConverter; import org.hibernate.metamodel.spi.MappingMetamodelImplementor; import org.hibernate.type.AbstractType; @@ -64,18 +66,16 @@ public class DiscriminatorType extends AbstractType implements BasicType, if ( discriminatorValue == null ) { return null; } - final String entityName = persister.getSubclassForDiscriminatorValue( discriminatorValue ); - if ( entityName == null ) { + final DiscriminatorValueDetails valueDetails = persister.getDiscriminatorMapping().resolveDiscriminatorValue( discriminatorValue ); + if ( valueDetails == null ) { throw new HibernateException( "Unable to resolve discriminator value [" + discriminatorValue + "] to entity name" ); } - final EntityPersister entityPersister = persister.getFactory() - .getRuntimeMetamodels() - .getMappingMetamodel() - .getEntityDescriptor( entityName ); + + final EntityMappingType indicatedEntity = valueDetails.getIndicatedEntity(); //noinspection unchecked - return entityPersister.getRepresentationStrategy().getMode() == RepresentationMode.POJO - ? (T) entityPersister.getJavaType().getJavaTypeClass() - : (T) entityName; + return indicatedEntity.getRepresentationStrategy().getMode() == RepresentationMode.POJO + ? (T) indicatedEntity.getJavaType().getJavaTypeClass() + : (T) indicatedEntity.getEntityName(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorValueDetailsImpl.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorValueDetailsImpl.java new file mode 100644 index 0000000000..ead226420b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorValueDetailsImpl.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html. + */ +package org.hibernate.persister.entity; + +import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping; +import org.hibernate.metamodel.mapping.EntityMappingType; + +/** + * @author Steve Ebersole + */ +public class DiscriminatorValueDetailsImpl implements EntityDiscriminatorMapping.DiscriminatorValueDetails { + private final Object value; + private final String jdbcLiteral; + private final EntityMappingType matchedEntityDescriptor; + + public DiscriminatorValueDetailsImpl(Object value, String jdbcLiteral, EntityMappingType matchedEntityDescriptor) { + this.value = value; + this.jdbcLiteral = jdbcLiteral; + this.matchedEntityDescriptor = matchedEntityDescriptor; + } + + @Override + public Object getValue() { + return value; + } + + @Override + public Object getSqlLiteralValue() { + return jdbcLiteral; + } + + @Override + public EntityMappingType getIndicatedEntity() { + return matchedEntityDescriptor; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPersister.java index 27bd570840..7b762f987d 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPersister.java @@ -34,7 +34,6 @@ import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate; import org.hibernate.internal.FilterAliasGenerator; import org.hibernate.internal.TableGroupFilterAliasGenerator; -import org.hibernate.loader.ast.spi.Loadable; import org.hibernate.loader.ast.spi.MultiIdLoadOptions; import org.hibernate.loader.ast.spi.MultiNaturalIdLoader; import org.hibernate.loader.ast.spi.NaturalIdLoader; @@ -103,8 +102,7 @@ import org.hibernate.type.descriptor.java.VersionJavaType; * @see org.hibernate.persister.spi.PersisterFactory * @see org.hibernate.persister.spi.PersisterClassResolver */ -public interface EntityPersister - extends EntityMappingType, Loadable, RootTableGroupProducer, AttributeSource { +public interface EntityPersister extends EntityMappingType, RootTableGroupProducer, AttributeSource { /** * Finish the initialization of this object. diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java index a56ec97efd..2af0d9b631 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java @@ -14,6 +14,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; import org.hibernate.AssertionFailure; @@ -70,6 +71,7 @@ import org.hibernate.type.BasicType; import org.hibernate.type.CompositeType; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.Type; +import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter; import org.jboss.logging.Logger; @@ -861,6 +863,32 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { } } + @Override + protected Map buildDiscriminatorValueMappings(PersistentClass bootEntityDescriptor, MappingModelCreationProcess modelCreationProcess) { + final MappingMetamodelImplementor mappingModel = modelCreationProcess.getCreationContext() + .getSessionFactory() + .getMappingMetamodel(); + + //noinspection unchecked + final JdbcLiteralFormatter jdbcLiteralFormatter = (JdbcLiteralFormatter) discriminatorType.getJdbcLiteralFormatter(); + final Dialect dialect = modelCreationProcess.getCreationContext().getSessionFactory().getJdbcServices().getDialect(); + + final Map valueMappings = new ConcurrentHashMap<>(); + + subclassesByDiscriminatorValue.forEach( (value, entityName) -> { + final String jdbcLiteral = value == NULL_DISCRIMINATOR || value == NOT_NULL_DISCRIMINATOR + ? null + : jdbcLiteralFormatter.toJdbcLiteral( value, dialect, null ); + final DiscriminatorValueDetailsImpl valueMapping = new DiscriminatorValueDetailsImpl( + value, + jdbcLiteral, + mappingModel.findEntityDescriptor( entityName ) + ); + valueMappings.put( value, valueMapping ); + } ); + return valueMappings; + } + @Override public void addDiscriminatorToInsertGroup(MutationGroupBuilder insertGroupBuilder) { if ( explicitDiscriminatorColumnName != null ) { @@ -1256,6 +1284,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { discriminatorValues, subclassNameByTableName, discriminatorMetadataType, + buildDiscriminatorValueMappings( bootEntityDescriptor, modelCreationProcess ), modelCreationProcess ); } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/Loadable.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/Loadable.java index e259fa614d..533e1f6fbd 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/Loadable.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/Loadable.java @@ -6,6 +6,8 @@ */ package org.hibernate.persister.entity; +import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping; +import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.type.Type; /** @@ -13,14 +15,20 @@ import org.hibernate.type.Type; * using a {@link org.hibernate.loader.ast.spi.Loader}. * * @author Gavin King + * + * @deprecated Use {@link EntityMappingType} */ +@Deprecated(since = "6", forRemoval = true) public interface Loadable extends EntityPersister { String ROWID_ALIAS = "rowid_"; /** * Does this persistent class have subclasses? + * + * @deprecated See {@link EntityMappingType#hasSubclasses()} */ + @Deprecated boolean hasSubclasses(); /** @@ -30,13 +38,19 @@ public interface Loadable extends EntityPersister { /** * Get the discriminator value + * + * @deprecated Use {@link EntityMappingType#getDiscriminatorValue()} instead */ + @Deprecated Object getDiscriminatorValue(); /** * Get the concrete subclass corresponding to the given discriminator * value + * + * @deprecated Use {@link EntityDiscriminatorMapping#resolveDiscriminatorValue} instead */ + @Deprecated String getSubclassForDiscriminatorValue(Object value); /** @@ -65,7 +79,10 @@ public interface Loadable extends EntityPersister { /** * @return the column name for the discriminator as specified in the mapping. + * + * @deprecated Use {@link EntityDiscriminatorMapping#getSelectionExpression()} instead */ + @Deprecated String getDiscriminatorColumnName(); /** diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/Queryable.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/Queryable.java index 729549d351..46273491ad 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/Queryable.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/Queryable.java @@ -6,6 +6,8 @@ */ package org.hibernate.persister.entity; +import org.hibernate.metamodel.mapping.EntityMappingType; + /** * Extends the generic {@link EntityPersister} contract to add * operations required by the Hibernate Query Language @@ -20,20 +22,30 @@ public interface Queryable extends Loadable, PropertyMapping, Joinable { /** * Is this an abstract class? + * + * @see EntityMappingType#isAbstract() */ boolean isAbstract(); /** * Is this class explicit polymorphism only? + * + * @see EntityMappingType#isExplicitPolymorphism() */ boolean isExplicitPolymorphism(); + /** * Get the class that this class is mapped as a subclass of - * not necessarily the direct superclass + * + * @see EntityMappingType#getSuperMappingType() */ String getMappedSuperclass(); + /** * Get the discriminator value for this particular concrete subclass, * as a string that may be embedded in a select statement + * + * @see EntityMappingType#getDiscriminatorSQLValue() */ String getDiscriminatorSQLValue(); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java index d69b27c024..afb5943432 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java @@ -12,6 +12,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Supplier; @@ -39,8 +40,10 @@ import org.hibernate.mapping.Selectable; import org.hibernate.mapping.Subclass; import org.hibernate.mapping.Table; import org.hibernate.mapping.Value; +import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping.DiscriminatorValueDetails; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.TableDetails; +import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess; import org.hibernate.metamodel.spi.MappingMetamodelImplementor; import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.persister.spi.PersisterCreationContext; @@ -66,10 +69,11 @@ import org.hibernate.sql.ast.tree.predicate.NullnessPredicate; import org.hibernate.sql.ast.tree.predicate.Predicate; import org.hibernate.sql.model.ast.builder.MutationGroupBuilder; import org.hibernate.sql.model.ast.builder.TableInsertBuilder; -import org.hibernate.sql.model.ast.builder.TableMutationBuilder; import org.hibernate.type.BasicType; import org.hibernate.type.Type; +import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter; +import static org.hibernate.persister.entity.DiscriminatorHelper.NOT_NULL_DISCRIMINATOR; import static org.hibernate.persister.entity.DiscriminatorHelper.NULL_DISCRIMINATOR; import static org.hibernate.sql.model.ast.builder.TableMutationBuilder.NULL; @@ -703,6 +707,35 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { return getTableSpan() > 1; } + @Override + protected Map buildDiscriminatorValueMappings( + PersistentClass bootEntityDescriptor, + MappingModelCreationProcess modelCreationProcess) { + final MappingMetamodelImplementor mappingModel = modelCreationProcess.getCreationContext() + .getSessionFactory() + .getMappingMetamodel(); + + //noinspection unchecked + final JdbcLiteralFormatter jdbcLiteralFormatter = (JdbcLiteralFormatter) discriminatorType.getJdbcLiteralFormatter(); + final Dialect dialect = modelCreationProcess.getCreationContext().getSessionFactory().getJdbcServices().getDialect(); + + final Map valueMappings = new ConcurrentHashMap<>(); + + subclassesByDiscriminatorValue.forEach( (value, entityName) -> { + final String jdbcLiteral = value == NULL_DISCRIMINATOR || value == NOT_NULL_DISCRIMINATOR + ? null + : jdbcLiteralFormatter.toJdbcLiteral( value, dialect, null ); + final DiscriminatorValueDetailsImpl valueMapping = new DiscriminatorValueDetailsImpl( + value, + jdbcLiteral, + mappingModel.findEntityDescriptor( entityName ) + ); + valueMappings.put( value, valueMapping ); + } ); + + return valueMappings; + } + @Override public String[] getConstraintOrderedTableNameClosure() { return constraintOrderedTableNames; diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java index 4ad1d094b1..188f88e28a 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java @@ -17,6 +17,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Supplier; @@ -64,6 +65,7 @@ import org.hibernate.sql.ast.tree.predicate.Predicate; import org.hibernate.type.BasicType; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.Type; +import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter; /** * An {@link EntityPersister} implementing the @@ -328,6 +330,29 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister { return subclassByDiscriminatorValue.get( value ); } + @Override + protected Map buildDiscriminatorValueMappings(PersistentClass bootEntityDescriptor, MappingModelCreationProcess modelCreationProcess) { + final MappingMetamodelImplementor mappingModel = modelCreationProcess.getCreationContext() + .getSessionFactory() + .getMappingMetamodel(); + + //noinspection unchecked + final JdbcLiteralFormatter jdbcLiteralFormatter = (JdbcLiteralFormatter) discriminatorType.getJdbcLiteralFormatter(); + final Dialect dialect = modelCreationProcess.getCreationContext().getSessionFactory().getJdbcServices().getDialect(); + + final Map valueMappings = new ConcurrentHashMap<>(); + + subclassByDiscriminatorValue.forEach( (value, entityName) -> { + final DiscriminatorValueDetailsImpl valueMapping = new DiscriminatorValueDetailsImpl( + value, + jdbcLiteralFormatter.toJdbcLiteral( value, dialect, null ), + mappingModel.findEntityDescriptor( entityName ) + ); + valueMappings.put( value, valueMapping ); + } ); + return valueMappings; + } + @Override public Serializable[] getPropertySpaces() { return spaces; diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/Fetchable.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/Fetchable.java index 836d68eeba..55073267c5 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/Fetchable.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/Fetchable.java @@ -12,6 +12,7 @@ import org.hibernate.mapping.IndexedConsumer; import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.ModelPart; +import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.spi.NavigablePath; /** @@ -22,7 +23,10 @@ import org.hibernate.spi.NavigablePath; @Incubating public interface Fetchable extends ModelPart { /** - * The name of the fetchable + * The name of the fetchable. This is the part's "local name". + * + * @see #getNavigableRole() + * @see NavigableRole#getLocalName() */ String getFetchableName(); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractEntityInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractEntityInitializer.java index ecd21df197..74233e871f 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractEntityInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractEntityInitializer.java @@ -27,7 +27,6 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.Status; import org.hibernate.event.service.spi.EventListenerGroup; -import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.PreLoadEvent; import org.hibernate.event.spi.PreLoadEventListener; import org.hibernate.internal.util.NullnessHelper; @@ -35,6 +34,8 @@ import org.hibernate.internal.util.StringHelper; import org.hibernate.loader.entity.CacheEntityLoaderHelper; import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMetadata; +import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping; +import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping.DiscriminatorValueDetails; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityValuedModelPart; import org.hibernate.metamodel.mapping.EntityVersionMapping; @@ -53,7 +54,6 @@ import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Fetch; import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.graph.basic.BasicResultAssembler; -import org.hibernate.sql.results.graph.entity.internal.EntityResultInitializer; import org.hibernate.sql.results.internal.NullValueAssembler; import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingState; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; @@ -342,32 +342,26 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces return entityDescriptor; } - final Object discriminatorDomainValue = discriminatorAssembler.extractRawValue( rowProcessingState ); - final String concreteEntityName = entityDescriptor.getDiscriminatorMapping() - .getConcreteEntityNameForDiscriminatorValue( discriminatorDomainValue ); + final EntityDiscriminatorMapping discriminatorMapping = entityDescriptor.getDiscriminatorMapping(); + assert discriminatorMapping != null; - if ( concreteEntityName == null ) { + final Object discriminator = discriminatorAssembler.extractRawValue( rowProcessingState ); + + final DiscriminatorValueDetails discriminatorDetails = discriminatorMapping.resolveDiscriminatorValue( discriminator ); + if ( discriminatorDetails == null ) { return entityDescriptor; } - final EntityPersister concreteType = session.getFactory() - .getRuntimeMetamodels() - .getMappingMetamodel() - .findEntityDescriptor( concreteEntityName ); - - if ( concreteType == null || !concreteType.isTypeOrSuperType( entityDescriptor ) ) { + if ( !discriminatorDetails.getIndicatedEntity().isTypeOrSuperType( entityDescriptor ) ) { throw new WrongClassException( - concreteEntityName, + discriminatorDetails.getIndicatedEntity().getEntityName(), null, entityDescriptor.getEntityName(), - discriminatorDomainValue + discriminator ); } - // verify that the `entityDescriptor` is either == concreteType or its super-type - assert concreteType.isTypeOrSuperType( entityDescriptor ); - - return concreteType; + return discriminatorDetails.getIndicatedEntity().getEntityPersister(); } protected void resolveEntityKey(RowProcessingState rowProcessingState) {