HHH-15883 - Expose MappingMetamodel via unwrap from SessionFactory

HHH-15884 - Clean-up EntityDiscriminatorMapping for API uses
This commit is contained in:
Steve Ebersole 2022-12-15 12:29:17 -06:00
parent 49c096f146
commit 2e0b4b3558
19 changed files with 370 additions and 129 deletions

View File

@ -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() { public CascadingFetchProfile getEnabledCascadingFetchProfile() {
return enabledCascadingFetchProfile; return enabledCascadingFetchProfile;
} }
/**
* Set the effective {@linkplain #getEnabledCascadingFetchProfile() cascading fetch-profile}
*/
public void setEnabledCascadingFetchProfile(CascadingFetchProfile enabledCascadingFetchProfile) { public void setEnabledCascadingFetchProfile(CascadingFetchProfile enabledCascadingFetchProfile) {
if ( sessionFactory == null ) { 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 // variety
throw new IllegalStateException( "Cannot modify context-less LoadQueryInfluencers" ); throw new IllegalStateException( "Cannot modify context-less LoadQueryInfluencers" );
} }

View File

@ -25,14 +25,6 @@ import java.util.function.Supplier;
import javax.naming.Reference; import javax.naming.Reference;
import javax.naming.StringRefAddr; 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.CustomEntityDirtinessStrategy;
import org.hibernate.EntityNameResolver; import org.hibernate.EntityNameResolver;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
@ -64,7 +56,6 @@ import org.hibernate.context.internal.ManagedSessionContext;
import org.hibernate.context.internal.ThreadLocalSessionContext; import org.hibernate.context.internal.ThreadLocalSessionContext;
import org.hibernate.context.spi.CurrentSessionContext; import org.hibernate.context.spi.CurrentSessionContext;
import org.hibernate.context.spi.CurrentTenantIdentifierResolver; import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.config.spi.ConfigurationService; import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess; import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.spi.JdbcServices; 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.spi.SessionImplementor;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform; import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.hibernate.event.spi.EventEngine; import org.hibernate.event.spi.EventEngine;
import org.hibernate.generator.Generator;
import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.factory.IdentifierGeneratorFactory; import org.hibernate.id.factory.IdentifierGeneratorFactory;
@ -91,11 +83,10 @@ import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.RootClass; import org.hibernate.mapping.RootClass;
import org.hibernate.metadata.CollectionMetadata; import org.hibernate.metadata.CollectionMetadata;
import org.hibernate.metamodel.internal.RuntimeMetamodelsImpl; 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.internal.MappingMetamodelImpl;
import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor;
import org.hibernate.metamodel.spi.MetamodelImplementor; import org.hibernate.metamodel.spi.MetamodelImplementor;
import org.hibernate.metamodel.spi.RuntimeMetamodelsImplementor;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Loadable; import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.entity.SessionFactoryBasedWrapperOptions; 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.EntityNotFoundDelegate;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer; import org.hibernate.proxy.LazyInitializer;
import org.hibernate.query.BindableType;
import org.hibernate.query.QueryLogging; import org.hibernate.query.QueryLogging;
import org.hibernate.query.hql.spi.SqmQueryImplementor; import org.hibernate.query.hql.spi.SqmQueryImplementor;
import org.hibernate.query.named.NamedObjectRepository; 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.stat.spi.StatisticsImplementor;
import org.hibernate.tool.schema.spi.DelayedDropAction; import org.hibernate.tool.schema.spi.DelayedDropAction;
import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator; import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator;
import org.hibernate.generator.Generator;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
import org.jboss.logging.Logger; 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; import static java.util.Collections.unmodifiableSet;
/** /**
@ -901,31 +898,19 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
@Override @Override
public <T> T unwrap(Class<T> type) { public <T> T unwrap(Class<T> type) {
if ( type.isAssignableFrom( SessionFactory.class ) ) { if ( type.isInstance( this ) ) {
return type.cast( this ); return type.cast( this );
} }
if ( type.isAssignableFrom( SessionFactoryImplementor.class ) ) { if ( type.isInstance( serviceRegistry ) ) {
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 ) ) {
return type.cast( serviceRegistry ); return type.cast( serviceRegistry );
} }
if ( type.isAssignableFrom( JdbcServices.class ) ) { if ( type.isInstance( jdbcServices ) ) {
return type.cast( jdbcServices ); return type.cast( jdbcServices );
} }
if ( type.isAssignableFrom( Cache.class ) || type.isAssignableFrom( org.hibernate.Cache.class ) ) { if ( type.isInstance( cacheAccess ) ) {
return type.cast( cacheAccess ); return type.cast( cacheAccess );
} }
@ -937,11 +922,11 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
return type.cast( runtimeMetamodels.getJpaMetamodel() ); return type.cast( runtimeMetamodels.getJpaMetamodel() );
} }
if ( type.isAssignableFrom( MetamodelImplementor.class ) || type.isAssignableFrom( MetadataImplementor.class ) ) { if ( type.isInstance( runtimeMetamodels.getMappingMetamodel() ) ) {
return type.cast( runtimeMetamodels.getMappingMetamodel() ); return type.cast( runtimeMetamodels.getMappingMetamodel() );
} }
if ( type.isAssignableFrom( QueryEngine.class ) ) { if ( type.isInstance( queryEngine ) ) {
return type.cast( queryEngine ); return type.cast( queryEngine );
} }

View File

@ -11,19 +11,37 @@ import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.sql.ast.tree.from.RootTableGroupProducer; import org.hibernate.sql.ast.tree.from.RootTableGroupProducer;
/** /**
* Contract for things that can be loaded by a Loader. * Common details for things that can be loaded by a {@linkplain Loader loader} - generally
* * {@linkplain org.hibernate.metamodel.mapping.EntityMappingType entities} and
* Generally speaking this is limited to entities and collections * {@linkplain org.hibernate.metamodel.mapping.PluralAttributeMapping plural attributes} (collections).
* *
* @see Loader * @see Loader
* @see org.hibernate.metamodel.mapping.EntityMappingType
* @see org.hibernate.metamodel.mapping.PluralAttributeMapping
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface Loadable extends ModelPart, RootTableGroupProducer { public interface Loadable extends ModelPart, RootTableGroupProducer {
boolean isAffectedByEnabledFilters(LoadQueryInfluencers influencers); /**
boolean isAffectedByEntityGraph(LoadQueryInfluencers influencers); * The name for this loadable, for use as the root when generating
boolean isAffectedByEnabledFetchProfiles(LoadQueryInfluencers influencers); * {@linkplain org.hibernate.spi.NavigablePath relative paths}
*/
String getRootPathName(); 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);
} }

View File

@ -8,7 +8,6 @@ package org.hibernate.metamodel.mapping;
import org.hibernate.engine.FetchStyle; import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.persister.entity.DiscriminatorType;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.ast.spi.SqlAstCreationState; import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.tree.expression.Expression; 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; 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.DiscriminatorColumn
* @see jakarta.persistence.DiscriminatorValue * @see jakarta.persistence.DiscriminatorValue
* *
@ -42,16 +46,51 @@ public interface EntityDiscriminatorMapping extends VirtualModelPart, BasicValue
return getPartName(); return getPartName();
} }
/**
* Is the discriminator defined by a physical column?
*/
boolean isPhysical();
@Override @Override
default int getFetchableKey() { default int getFetchableKey() {
return -2; 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 * Create the appropriate SQL expression for this discriminator
@ -66,7 +105,7 @@ public interface EntityDiscriminatorMapping extends VirtualModelPart, BasicValue
SqlAstCreationState creationState); SqlAstCreationState creationState);
@Override @Override
BasicFetch generateFetch( BasicFetch<?> generateFetch(
FetchParent fetchParent, FetchParent fetchParent,
NavigablePath fetchablePath, NavigablePath fetchablePath,
FetchTiming fetchTiming, FetchTiming fetchTiming,

View File

@ -6,10 +6,10 @@
*/ */
package org.hibernate.metamodel.mapping.internal; package org.hibernate.metamodel.mapping.internal;
import java.util.Map;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.mapping.IndexedConsumer; import org.hibernate.mapping.IndexedConsumer;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping; 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.mapping.SelectableConsumer;
import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.persister.entity.DiscriminatorType; import org.hibernate.persister.entity.DiscriminatorType;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.ast.spi.SqlAstCreationState; import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlExpressionResolver; 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.BasicType;
import org.hibernate.type.descriptor.java.JavaType; 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()` * @implNote `discriminatorType` represents the mapping to Class, whereas `discriminatorType.getUnderlyingType()`
* represents the "raw" JDBC mapping (String, Integer, etc) * 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 { public abstract class AbstractDiscriminatorMapping implements EntityDiscriminatorMapping {
private final NavigableRole role; private final NavigableRole role;
private final EntityPersister entityDescriptor; private final JdbcMapping jdbcMapping;
private final DiscriminatorType<?> discriminatorType;
private final SessionFactoryImplementor sessionFactory; private final EntityMappingType entityDescriptor;
private final Map<Object, DiscriminatorValueDetails> valueMappings;
private final DiscriminatorType<Object> discriminatorType;
public AbstractDiscriminatorMapping( public AbstractDiscriminatorMapping(
EntityPersister entityDescriptor, EntityMappingType entityDescriptor,
DiscriminatorType<?> discriminatorType, DiscriminatorType<?> discriminatorType,
Map<Object, DiscriminatorValueDetails> valueMappings,
MappingModelCreationProcess creationProcess) { MappingModelCreationProcess creationProcess) {
this.jdbcMapping = discriminatorType.getUnderlyingType().getJdbcMapping();
this.entityDescriptor = entityDescriptor; this.entityDescriptor = entityDescriptor;
this.discriminatorType = discriminatorType; this.valueMappings = valueMappings;
role = entityDescriptor.getNavigableRole().append( EntityDiscriminatorMapping.ROLE_NAME ); this.role = entityDescriptor.getNavigableRole().append( EntityDiscriminatorMapping.ROLE_NAME );
sessionFactory = creationProcess.getCreationContext().getSessionFactory();
//noinspection unchecked
this.discriminatorType = (DiscriminatorType<Object>) discriminatorType;
} }
public EntityPersister getEntityDescriptor() { public EntityMappingType getEntityDescriptor() {
return entityDescriptor; return entityDescriptor;
} }
@Override
public DiscriminatorType getDiscriminatorType() {
return discriminatorType;
}
public BasicType<?> getUnderlyingJdbcMappingType() { public BasicType<?> getUnderlyingJdbcMappingType() {
return discriminatorType.getUnderlyingType(); return discriminatorType.getUnderlyingType();
} }
public SessionFactoryImplementor getSessionFactory() {
return sessionFactory;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// EntityDiscriminatorMapping // EntityDiscriminatorMapping
@ -89,8 +89,17 @@ public abstract class AbstractDiscriminatorMapping implements EntityDiscriminato
} }
@Override @Override
public String getConcreteEntityNameForDiscriminatorValue(Object value) { public DiscriminatorValueDetails resolveDiscriminatorValue(Object value) {
return getEntityDescriptor().getSubclassForDiscriminatorValue( 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 @Override
@ -108,24 +117,28 @@ public abstract class AbstractDiscriminatorMapping implements EntityDiscriminato
return getJdbcMapping().getJavaTypeDescriptor(); return getJdbcMapping().getJavaTypeDescriptor();
} }
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override @Override
public <T> DomainResult<T> createDomainResult( public DomainResult createDomainResult(
NavigablePath navigablePath, NavigablePath navigablePath,
TableGroup tableGroup, TableGroup tableGroup,
String resultVariable, String resultVariable,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
// create a SqlSelection based on the underlying JdbcMapping
final SqlSelection sqlSelection = resolveSqlSelection( final SqlSelection sqlSelection = resolveSqlSelection(
navigablePath, navigablePath,
getUnderlyingJdbcMappingType(), jdbcMapping,
tableGroup, tableGroup,
null, null,
creationState.getSqlAstCreationState() creationState.getSqlAstCreationState()
); );
return new BasicResult<>( // return a BasicResult with conversion the entity class or entity-name
return new BasicResult(
sqlSelection.getValuesArrayPosition(), sqlSelection.getValuesArrayPosition(),
resultVariable, resultVariable,
discriminatorType, discriminatorType.getJavaTypeDescriptor(),
discriminatorType.getValueConverter(),
navigablePath navigablePath
); );
} }
@ -160,19 +173,22 @@ public abstract class AbstractDiscriminatorMapping implements EntityDiscriminato
assert tableGroup != null; assert tableGroup != null;
// create a SqlSelection based on the underlying JdbcMapping
final SqlSelection sqlSelection = resolveSqlSelection( final SqlSelection sqlSelection = resolveSqlSelection(
fetchablePath, fetchablePath,
getUnderlyingJdbcMappingType(), jdbcMapping,
tableGroup, tableGroup,
fetchParent, fetchParent,
creationState.getSqlAstCreationState() creationState.getSqlAstCreationState()
); );
// return a BasicFetch with conversion the entity class or entity-name
return new BasicFetch<>( return new BasicFetch<>(
sqlSelection.getValuesArrayPosition(), sqlSelection.getValuesArrayPosition(),
fetchParent, fetchParent,
fetchablePath, fetchablePath,
this, this,
discriminatorType.getValueConverter(),
fetchTiming, fetchTiming,
creationState creationState
); );
@ -183,7 +199,13 @@ public abstract class AbstractDiscriminatorMapping implements EntityDiscriminato
NavigablePath navigablePath, NavigablePath navigablePath,
TableGroup tableGroup, TableGroup tableGroup,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
resolveSqlSelection( navigablePath, getUnderlyingJdbcMappingType(), tableGroup, null, creationState.getSqlAstCreationState() ); resolveSqlSelection(
navigablePath,
jdbcMapping,
tableGroup,
null,
creationState.getSqlAstCreationState()
);
} }
@Override @Override
@ -193,7 +215,7 @@ public abstract class AbstractDiscriminatorMapping implements EntityDiscriminato
DomainResultCreationState creationState, DomainResultCreationState creationState,
BiConsumer<SqlSelection, JdbcMapping> selectionConsumer) { BiConsumer<SqlSelection, JdbcMapping> selectionConsumer) {
selectionConsumer.accept( selectionConsumer.accept(
resolveSqlSelection( navigablePath, getUnderlyingJdbcMappingType(), tableGroup, null, creationState.getSqlAstCreationState() ), resolveSqlSelection( navigablePath, jdbcMapping, tableGroup, null, creationState.getSqlAstCreationState() ),
getJdbcMapping() getJdbcMapping()
); );
} }
@ -204,13 +226,13 @@ public abstract class AbstractDiscriminatorMapping implements EntityDiscriminato
int offset, int offset,
JdbcValuesConsumer valuesConsumer, JdbcValuesConsumer valuesConsumer,
SharedSessionContractImplementor session) { SharedSessionContractImplementor session) {
valuesConsumer.consume( offset, value, getJdbcMapping() ); valuesConsumer.consume( offset, value, jdbcMapping );
return getJdbcTypeCount(); return getJdbcTypeCount();
} }
@Override @Override
public int forEachJdbcType(int offset, IndexedConsumer<JdbcMapping> action) { public int forEachJdbcType(int offset, IndexedConsumer<JdbcMapping> action) {
action.accept( offset, getJdbcMapping() ); action.accept( offset, jdbcMapping );
return getJdbcTypeCount(); return getJdbcTypeCount();
} }

View File

@ -50,8 +50,9 @@ public class CaseStatementDiscriminatorMappingImpl extends AbstractDiscriminator
String[] discriminatorValues, String[] discriminatorValues,
Map<String,String> subEntityNameByTableName, Map<String,String> subEntityNameByTableName,
DiscriminatorType<?> incomingDiscriminatorType, DiscriminatorType<?> incomingDiscriminatorType,
Map<Object, DiscriminatorValueDetails> valueMappings,
MappingModelCreationProcess creationProcess) { MappingModelCreationProcess creationProcess) {
super( entityDescriptor, incomingDiscriminatorType, creationProcess ); super( entityDescriptor, incomingDiscriminatorType, valueMappings, creationProcess );
for ( int i = 0; i < discriminatorValues.length; i++ ) { for ( int i = 0; i < discriminatorValues.length; i++ ) {
final String tableName = tableNames[notNullColumnTableNumbers[i]]; final String tableName = tableNames[notNullColumnTableNumbers[i]];

View File

@ -6,9 +6,11 @@
*/ */
package org.hibernate.metamodel.mapping.internal; 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.metamodel.mapping.JdbcMapping;
import org.hibernate.persister.entity.DiscriminatorType; import org.hibernate.persister.entity.DiscriminatorType;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.ast.spi.SqlAstCreationState; import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlExpressionResolver; import org.hibernate.sql.ast.spi.SqlExpressionResolver;
@ -30,8 +32,7 @@ public class ExplicitColumnDiscriminatorMappingImpl extends AbstractDiscriminato
private final Integer scale; private final Integer scale;
public ExplicitColumnDiscriminatorMappingImpl( public ExplicitColumnDiscriminatorMappingImpl(
EntityPersister entityDescriptor, EntityMappingType entityDescriptor,
DiscriminatorType<?> discriminatorType,
String tableExpression, String tableExpression,
String columnExpression, String columnExpression,
boolean isFormula, boolean isFormula,
@ -40,8 +41,10 @@ public class ExplicitColumnDiscriminatorMappingImpl extends AbstractDiscriminato
Long length, Long length,
Integer precision, Integer precision,
Integer scale, Integer scale,
DiscriminatorType<?> discriminatorType,
Map<Object, DiscriminatorValueDetails> valueMappings,
MappingModelCreationProcess creationProcess) { MappingModelCreationProcess creationProcess) {
super( entityDescriptor, discriminatorType, creationProcess ); super( entityDescriptor, discriminatorType, valueMappings, creationProcess );
this.tableExpression = tableExpression; this.tableExpression = tableExpression;
this.isPhysical = isPhysical; this.isPhysical = isPhysical;
this.columnDefinition = columnDefinition; this.columnDefinition = columnDefinition;

View File

@ -161,6 +161,7 @@ import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.DiscriminatedAssociationModelPart; import org.hibernate.metamodel.mapping.DiscriminatedAssociationModelPart;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping; import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping.DiscriminatorValueDetails;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityRowIdMapping; import org.hibernate.metamodel.mapping.EntityRowIdMapping;
@ -4992,16 +4993,23 @@ public abstract class AbstractEntityPersister
} }
return new ExplicitColumnDiscriminatorMappingImpl ( return new ExplicitColumnDiscriminatorMappingImpl (
this, this,
(DiscriminatorType<?>) getTypeDiscriminatorMetadata().getResolutionType(),
getTableName(), getTableName(),
discriminatorColumnExpression, discriminatorColumnExpression,
getDiscriminatorFormulaTemplate() != null, getDiscriminatorFormulaTemplate() != null,
isPhysicalDiscriminator(), isPhysicalDiscriminator(),
columnDefinition, length, precision, scale, modelCreationProcess columnDefinition, length, precision, scale,
(DiscriminatorType<?>) getTypeDiscriminatorMetadata().getResolutionType(),
buildDiscriminatorValueMappings( bootEntityDescriptor, modelCreationProcess ),
modelCreationProcess
); );
} }
} }
protected abstract Map<Object, DiscriminatorValueDetails> buildDiscriminatorValueMappings(
PersistentClass bootEntityDescriptor,
MappingModelCreationProcess modelCreationProcess);
protected EntityVersionMapping generateVersionMapping( protected EntityVersionMapping generateVersionMapping(
Supplier<?> templateInstanceCreator, Supplier<?> templateInstanceCreator,
PersistentClass bootEntityDescriptor, PersistentClass bootEntityDescriptor,

View File

@ -6,6 +6,7 @@
*/ */
package org.hibernate.persister.entity; package org.hibernate.persister.entity;
import org.hibernate.Internal;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -14,18 +15,18 @@ import org.hibernate.mapping.PersistentClass;
import org.hibernate.sql.InFragment; import org.hibernate.sql.InFragment;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
import org.hibernate.type.descriptor.java.JavaType;
/** /**
* Operations needed by persisters for working with discriminators. * Operations needed by persisters for working with discriminators.
* *
* @author Gavin King * @author Gavin King
*/ */
class DiscriminatorHelper { @Internal
public class DiscriminatorHelper {
static final Object NULL_DISCRIMINATOR = new MarkerObject( "<null discriminator>" ); public static final Object NULL_DISCRIMINATOR = new MarkerObject( "<null discriminator>" );
static final Object NOT_NULL_DISCRIMINATOR = new MarkerObject( "<not null discriminator>" ); public static final Object NOT_NULL_DISCRIMINATOR = new MarkerObject( "<not null discriminator>" );
static BasicType<?> getDiscriminatorType(PersistentClass persistentClass) { static BasicType<?> getDiscriminatorType(PersistentClass persistentClass) {
Type discriminatorType = persistentClass.getDiscriminator().getType(); Type discriminatorType = persistentClass.getDiscriminator().getType();
@ -51,8 +52,7 @@ class DiscriminatorHelper {
return discriminatorSqlLiteral( return discriminatorSqlLiteral(
getDiscriminatorType( persistentClass ), getDiscriminatorType( persistentClass ),
persistentClass, persistentClass,
dialect, dialect
factory.getWrapperOptions()
); );
} }
} }
@ -82,17 +82,21 @@ class DiscriminatorHelper {
private static <T> String discriminatorSqlLiteral( private static <T> String discriminatorSqlLiteral(
BasicType<T> discriminatorType, BasicType<T> discriminatorType,
PersistentClass persistentClass, PersistentClass persistentClass,
Dialect dialect, Dialect dialect) {
WrapperOptions wrapperOptions) { return jdbcLiteral(
final JavaType<T> javaType = discriminatorType.getJavaTypeDescriptor(); discriminatorType.getJavaTypeDescriptor().fromString( persistentClass.getDiscriminatorValue() ),
try { discriminatorType.getJdbcLiteralFormatter(),
return discriminatorType.getJdbcLiteralFormatter() dialect
.toJdbcLiteral(
javaType.fromString( persistentClass.getDiscriminatorValue() ),
dialect,
wrapperOptions
); );
} }
public static <T> String jdbcLiteral(
T value,
JdbcLiteralFormatter<T> formatter,
Dialect dialect) {
try {
return formatter.toJdbcLiteral( value, dialect, null );
}
catch (Exception e) { catch (Exception e) {
throw new MappingException( "Could not format discriminator value to SQL string", e ); throw new MappingException( "Could not format discriminator value to SQL string", e );
} }

View File

@ -19,6 +19,8 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.metamodel.RepresentationMode; 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.model.convert.spi.BasicValueConverter;
import org.hibernate.metamodel.spi.MappingMetamodelImplementor; import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
import org.hibernate.type.AbstractType; import org.hibernate.type.AbstractType;
@ -64,18 +66,16 @@ public class DiscriminatorType<T> extends AbstractType implements BasicType<T>,
if ( discriminatorValue == null ) { if ( discriminatorValue == null ) {
return null; return null;
} }
final String entityName = persister.getSubclassForDiscriminatorValue( discriminatorValue ); final DiscriminatorValueDetails valueDetails = persister.getDiscriminatorMapping().resolveDiscriminatorValue( discriminatorValue );
if ( entityName == null ) { if ( valueDetails == null ) {
throw new HibernateException( "Unable to resolve discriminator value [" + discriminatorValue + "] to entity name" ); throw new HibernateException( "Unable to resolve discriminator value [" + discriminatorValue + "] to entity name" );
} }
final EntityPersister entityPersister = persister.getFactory()
.getRuntimeMetamodels() final EntityMappingType indicatedEntity = valueDetails.getIndicatedEntity();
.getMappingMetamodel()
.getEntityDescriptor( entityName );
//noinspection unchecked //noinspection unchecked
return entityPersister.getRepresentationStrategy().getMode() == RepresentationMode.POJO return indicatedEntity.getRepresentationStrategy().getMode() == RepresentationMode.POJO
? (T) entityPersister.getJavaType().getJavaTypeClass() ? (T) indicatedEntity.getJavaType().getJavaTypeClass()
: (T) entityName; : (T) indicatedEntity.getEntityName();
} }
@Override @Override

View File

@ -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;
}
}

View File

@ -34,7 +34,6 @@ import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate; import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
import org.hibernate.internal.FilterAliasGenerator; import org.hibernate.internal.FilterAliasGenerator;
import org.hibernate.internal.TableGroupFilterAliasGenerator; 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.MultiIdLoadOptions;
import org.hibernate.loader.ast.spi.MultiNaturalIdLoader; import org.hibernate.loader.ast.spi.MultiNaturalIdLoader;
import org.hibernate.loader.ast.spi.NaturalIdLoader; 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.PersisterFactory
* @see org.hibernate.persister.spi.PersisterClassResolver * @see org.hibernate.persister.spi.PersisterClassResolver
*/ */
public interface EntityPersister public interface EntityPersister extends EntityMappingType, RootTableGroupProducer, AttributeSource {
extends EntityMappingType, Loadable, RootTableGroupProducer, AttributeSource {
/** /**
* Finish the initialization of this object. * Finish the initialization of this object.

View File

@ -14,6 +14,7 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.hibernate.AssertionFailure; import org.hibernate.AssertionFailure;
@ -70,6 +71,7 @@ import org.hibernate.type.BasicType;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -861,6 +863,32 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
} }
} }
@Override
protected Map<Object, EntityDiscriminatorMapping.DiscriminatorValueDetails> buildDiscriminatorValueMappings(PersistentClass bootEntityDescriptor, MappingModelCreationProcess modelCreationProcess) {
final MappingMetamodelImplementor mappingModel = modelCreationProcess.getCreationContext()
.getSessionFactory()
.getMappingMetamodel();
//noinspection unchecked
final JdbcLiteralFormatter<Object> jdbcLiteralFormatter = (JdbcLiteralFormatter<Object>) discriminatorType.getJdbcLiteralFormatter();
final Dialect dialect = modelCreationProcess.getCreationContext().getSessionFactory().getJdbcServices().getDialect();
final Map<Object, EntityDiscriminatorMapping.DiscriminatorValueDetails> 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 @Override
public void addDiscriminatorToInsertGroup(MutationGroupBuilder insertGroupBuilder) { public void addDiscriminatorToInsertGroup(MutationGroupBuilder insertGroupBuilder) {
if ( explicitDiscriminatorColumnName != null ) { if ( explicitDiscriminatorColumnName != null ) {
@ -1256,6 +1284,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
discriminatorValues, discriminatorValues,
subclassNameByTableName, subclassNameByTableName,
discriminatorMetadataType, discriminatorMetadataType,
buildDiscriminatorValueMappings( bootEntityDescriptor, modelCreationProcess ),
modelCreationProcess modelCreationProcess
); );
} }

View File

@ -6,6 +6,8 @@
*/ */
package org.hibernate.persister.entity; package org.hibernate.persister.entity;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
@ -13,14 +15,20 @@ import org.hibernate.type.Type;
* using a {@link org.hibernate.loader.ast.spi.Loader}. * using a {@link org.hibernate.loader.ast.spi.Loader}.
* *
* @author Gavin King * @author Gavin King
*
* @deprecated Use {@link EntityMappingType}
*/ */
@Deprecated(since = "6", forRemoval = true)
public interface Loadable extends EntityPersister { public interface Loadable extends EntityPersister {
String ROWID_ALIAS = "rowid_"; String ROWID_ALIAS = "rowid_";
/** /**
* Does this persistent class have subclasses? * Does this persistent class have subclasses?
*
* @deprecated See {@link EntityMappingType#hasSubclasses()}
*/ */
@Deprecated
boolean hasSubclasses(); boolean hasSubclasses();
/** /**
@ -30,13 +38,19 @@ public interface Loadable extends EntityPersister {
/** /**
* Get the discriminator value * Get the discriminator value
*
* @deprecated Use {@link EntityMappingType#getDiscriminatorValue()} instead
*/ */
@Deprecated
Object getDiscriminatorValue(); Object getDiscriminatorValue();
/** /**
* Get the concrete subclass corresponding to the given discriminator * Get the concrete subclass corresponding to the given discriminator
* value * value
*
* @deprecated Use {@link EntityDiscriminatorMapping#resolveDiscriminatorValue} instead
*/ */
@Deprecated
String getSubclassForDiscriminatorValue(Object value); 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. * @return the column name for the discriminator as specified in the mapping.
*
* @deprecated Use {@link EntityDiscriminatorMapping#getSelectionExpression()} instead
*/ */
@Deprecated
String getDiscriminatorColumnName(); String getDiscriminatorColumnName();
/** /**

View File

@ -6,6 +6,8 @@
*/ */
package org.hibernate.persister.entity; package org.hibernate.persister.entity;
import org.hibernate.metamodel.mapping.EntityMappingType;
/** /**
* Extends the generic {@link EntityPersister} contract to add * Extends the generic {@link EntityPersister} contract to add
* operations required by the Hibernate Query Language * operations required by the Hibernate Query Language
@ -20,20 +22,30 @@ public interface Queryable extends Loadable, PropertyMapping, Joinable {
/** /**
* Is this an abstract class? * Is this an abstract class?
*
* @see EntityMappingType#isAbstract()
*/ */
boolean isAbstract(); boolean isAbstract();
/** /**
* Is this class explicit polymorphism only? * Is this class explicit polymorphism only?
*
* @see EntityMappingType#isExplicitPolymorphism()
*/ */
boolean isExplicitPolymorphism(); boolean isExplicitPolymorphism();
/** /**
* Get the class that this class is mapped as a subclass of - * Get the class that this class is mapped as a subclass of -
* not necessarily the direct superclass * not necessarily the direct superclass
*
* @see EntityMappingType#getSuperMappingType()
*/ */
String getMappedSuperclass(); String getMappedSuperclass();
/** /**
* Get the discriminator value for this particular concrete subclass, * Get the discriminator value for this particular concrete subclass,
* as a string that may be embedded in a select statement * as a string that may be embedded in a select statement
*
* @see EntityMappingType#getDiscriminatorSQLValue()
*/ */
String getDiscriminatorSQLValue(); String getDiscriminatorSQLValue();

View File

@ -12,6 +12,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -39,8 +40,10 @@ import org.hibernate.mapping.Selectable;
import org.hibernate.mapping.Subclass; import org.hibernate.mapping.Subclass;
import org.hibernate.mapping.Table; import org.hibernate.mapping.Table;
import org.hibernate.mapping.Value; import org.hibernate.mapping.Value;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping.DiscriminatorValueDetails;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.TableDetails; import org.hibernate.metamodel.mapping.TableDetails;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.metamodel.spi.MappingMetamodelImplementor; import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.persister.spi.PersisterCreationContext; 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.ast.tree.predicate.Predicate;
import org.hibernate.sql.model.ast.builder.MutationGroupBuilder; import org.hibernate.sql.model.ast.builder.MutationGroupBuilder;
import org.hibernate.sql.model.ast.builder.TableInsertBuilder; 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.BasicType;
import org.hibernate.type.Type; 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.persister.entity.DiscriminatorHelper.NULL_DISCRIMINATOR;
import static org.hibernate.sql.model.ast.builder.TableMutationBuilder.NULL; import static org.hibernate.sql.model.ast.builder.TableMutationBuilder.NULL;
@ -703,6 +707,35 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
return getTableSpan() > 1; return getTableSpan() > 1;
} }
@Override
protected Map<Object, DiscriminatorValueDetails> buildDiscriminatorValueMappings(
PersistentClass bootEntityDescriptor,
MappingModelCreationProcess modelCreationProcess) {
final MappingMetamodelImplementor mappingModel = modelCreationProcess.getCreationContext()
.getSessionFactory()
.getMappingMetamodel();
//noinspection unchecked
final JdbcLiteralFormatter<Object> jdbcLiteralFormatter = (JdbcLiteralFormatter<Object>) discriminatorType.getJdbcLiteralFormatter();
final Dialect dialect = modelCreationProcess.getCreationContext().getSessionFactory().getJdbcServices().getDialect();
final Map<Object, DiscriminatorValueDetails> 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 @Override
public String[] getConstraintOrderedTableNameClosure() { public String[] getConstraintOrderedTableNameClosure() {
return constraintOrderedTableNames; return constraintOrderedTableNames;

View File

@ -17,6 +17,7 @@ import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier; 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.BasicType;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
/** /**
* An {@link EntityPersister} implementing the * An {@link EntityPersister} implementing the
@ -328,6 +330,29 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
return subclassByDiscriminatorValue.get( value ); return subclassByDiscriminatorValue.get( value );
} }
@Override
protected Map<Object, EntityDiscriminatorMapping.DiscriminatorValueDetails> buildDiscriminatorValueMappings(PersistentClass bootEntityDescriptor, MappingModelCreationProcess modelCreationProcess) {
final MappingMetamodelImplementor mappingModel = modelCreationProcess.getCreationContext()
.getSessionFactory()
.getMappingMetamodel();
//noinspection unchecked
final JdbcLiteralFormatter<Object> jdbcLiteralFormatter = (JdbcLiteralFormatter<Object>) discriminatorType.getJdbcLiteralFormatter();
final Dialect dialect = modelCreationProcess.getCreationContext().getSessionFactory().getJdbcServices().getDialect();
final Map<Object, EntityDiscriminatorMapping.DiscriminatorValueDetails> 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 @Override
public Serializable[] getPropertySpaces() { public Serializable[] getPropertySpaces() {
return spaces; return spaces;

View File

@ -12,6 +12,7 @@ import org.hibernate.mapping.IndexedConsumer;
import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
/** /**
@ -22,7 +23,10 @@ import org.hibernate.spi.NavigablePath;
@Incubating @Incubating
public interface Fetchable extends ModelPart { 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(); String getFetchableName();

View File

@ -27,7 +27,6 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.spi.Status; import org.hibernate.engine.spi.Status;
import org.hibernate.event.service.spi.EventListenerGroup; import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.PreLoadEvent; import org.hibernate.event.spi.PreLoadEvent;
import org.hibernate.event.spi.PreLoadEventListener; import org.hibernate.event.spi.PreLoadEventListener;
import org.hibernate.internal.util.NullnessHelper; 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.loader.entity.CacheEntityLoaderHelper;
import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.AttributeMetadata; 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.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityValuedModelPart; import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.EntityVersionMapping; 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.Fetch;
import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.basic.BasicResultAssembler; 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.internal.NullValueAssembler;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingState; import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingState;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
@ -342,32 +342,26 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
return entityDescriptor; return entityDescriptor;
} }
final Object discriminatorDomainValue = discriminatorAssembler.extractRawValue( rowProcessingState ); final EntityDiscriminatorMapping discriminatorMapping = entityDescriptor.getDiscriminatorMapping();
final String concreteEntityName = entityDescriptor.getDiscriminatorMapping() assert discriminatorMapping != null;
.getConcreteEntityNameForDiscriminatorValue( discriminatorDomainValue );
if ( concreteEntityName == null ) { final Object discriminator = discriminatorAssembler.extractRawValue( rowProcessingState );
final DiscriminatorValueDetails discriminatorDetails = discriminatorMapping.resolveDiscriminatorValue( discriminator );
if ( discriminatorDetails == null ) {
return entityDescriptor; return entityDescriptor;
} }
final EntityPersister concreteType = session.getFactory() if ( !discriminatorDetails.getIndicatedEntity().isTypeOrSuperType( entityDescriptor ) ) {
.getRuntimeMetamodels()
.getMappingMetamodel()
.findEntityDescriptor( concreteEntityName );
if ( concreteType == null || !concreteType.isTypeOrSuperType( entityDescriptor ) ) {
throw new WrongClassException( throw new WrongClassException(
concreteEntityName, discriminatorDetails.getIndicatedEntity().getEntityName(),
null, null,
entityDescriptor.getEntityName(), entityDescriptor.getEntityName(),
discriminatorDomainValue discriminator
); );
} }
// verify that the `entityDescriptor` is either == concreteType or its super-type return discriminatorDetails.getIndicatedEntity().getEntityPersister();
assert concreteType.isTypeOrSuperType( entityDescriptor );
return concreteType;
} }
protected void resolveEntityKey(RowProcessingState rowProcessingState) { protected void resolveEntityKey(RowProcessingState rowProcessingState) {