improvements to how discriminators are handled by AbstractEntityPersister

This commit is contained in:
Gavin 2022-12-24 14:55:20 +01:00 committed by Gavin King
parent b1e2eca53e
commit e918f92f48
10 changed files with 171 additions and 205 deletions

View File

@ -641,9 +641,11 @@ public class EntityBinder {
processDiscriminatorOptions();
final AnnotatedDiscriminatorColumn discriminatorColumn = processSingleTableDiscriminatorProperties( inheritanceState );
if ( !inheritanceState.hasParents() ) { // todo : sucks that this is separate from RootClass distinction
final RootClass rootClass = (RootClass) persistentClass;
if ( inheritanceState.hasSiblings()
|| discriminatorColumn != null && !discriminatorColumn.isImplicit() ) {
bindDiscriminatorColumnToRootPersistentClass( (RootClass) persistentClass, discriminatorColumn, holder );
bindDiscriminatorColumnToRootPersistentClass(rootClass, discriminatorColumn, holder );
rootClass.setForceDiscriminator( isForceDiscriminatorInSelects() );
}
}
}
@ -668,13 +670,15 @@ public class EntityBinder {
final AnnotatedDiscriminatorColumn discriminatorColumn = processJoinedDiscriminatorProperties( state );
if ( !state.hasParents() ) { // todo : sucks that this is separate from RootClass distinction
final RootClass rootClass = (RootClass) persistentClass;
// the class we're processing is the root of the hierarchy, so
// let's see if we had a discriminator column (it's perfectly
// valid for joined inheritance to not have a discriminator)
if ( discriminatorColumn != null ) {
// we do have a discriminator column
if ( state.hasSiblings() || !discriminatorColumn.isImplicit() ) {
bindDiscriminatorColumnToRootPersistentClass( (RootClass) persistentClass, discriminatorColumn, holder );
bindDiscriminatorColumnToRootPersistentClass(rootClass, discriminatorColumn, holder );
rootClass.setForceDiscriminator( isForceDiscriminatorInSelects() );
}
}
}
@ -750,7 +754,6 @@ public class EntityBinder {
new NullableDiscriminatorColumnSecondPass( rootClass.getEntityName() )
);
}
rootClass.setForceDiscriminator( isForceDiscriminatorInSelects() );
if ( insertableDiscriminator != null ) {
rootClass.setDiscriminatorInsertable( insertableDiscriminator );
}

View File

@ -11,7 +11,6 @@ import java.lang.reflect.Constructor;
import org.hibernate.InstantiationException;
import org.hibernate.PropertyNotFoundException;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;

View File

@ -48,6 +48,7 @@ public class CaseStatementDiscriminatorMappingImpl extends AbstractDiscriminator
int[] notNullColumnTableNumbers,
String[] notNullColumnNames,
String[] discriminatorValues,
boolean[] discriminatorAbstract,
Map<String,String> subEntityNameByTableName,
DiscriminatorType<?> incomingDiscriminatorType,
Map<Object, DiscriminatorValueDetails> valueMappings,
@ -55,24 +56,24 @@ public class CaseStatementDiscriminatorMappingImpl extends AbstractDiscriminator
super( entityDescriptor, incomingDiscriminatorType, valueMappings, creationProcess );
for ( int i = 0; i < discriminatorValues.length; i++ ) {
if ( !discriminatorAbstract[i] ) {
final String tableName = tableNames[notNullColumnTableNumbers[i]];
final String subEntityName = subEntityNameByTableName.get( tableName );
final String oneSubEntityColumn = notNullColumnNames[i];
final String rawDiscriminatorValue = discriminatorValues[i];
final Object discriminatorValue = getUnderlyingJdbcMappingType().getJavaTypeDescriptor().wrap( rawDiscriminatorValue, null );
final String discriminatorValue = discriminatorValues[i];
tableDiscriminatorDetailsMap.put(
tableName,
new TableDiscriminatorDetails(
tableName,
oneSubEntityColumn,
discriminatorValue,
getUnderlyingJdbcMappingType().getJavaTypeDescriptor()
.wrap( discriminatorValue, null ),
subEntityName
)
);
}
}
}
@Override
public boolean hasPhysicalColumn() {

View File

@ -26,6 +26,7 @@ import java.util.Objects;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
@ -111,7 +112,6 @@ import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.FilterAliasGenerator;
import org.hibernate.internal.FilterHelper;
import org.hibernate.internal.util.LazyValue;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
@ -191,6 +191,7 @@ import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.metamodel.spi.EntityInstantiator;
import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.mutation.DeleteCoordinator;
@ -203,7 +204,6 @@ import org.hibernate.persister.entity.mutation.UpdateCoordinatorStandard;
import org.hibernate.persister.internal.ImmutableAttributeMappingList;
import org.hibernate.persister.internal.SqlFragmentPredicate;
import org.hibernate.persister.spi.PersisterCreationContext;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.property.access.spi.Setter;
import org.hibernate.query.SemanticException;
@ -275,6 +275,7 @@ import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.MutabilityPlan;
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
import static java.util.Collections.emptySet;
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
@ -284,6 +285,7 @@ import static org.hibernate.engine.internal.ManagedTypeHelper.processIfSelfDirti
import static org.hibernate.engine.internal.Versioning.isVersionIncrementRequired;
import static org.hibernate.generator.EventType.INSERT;
import static org.hibernate.generator.EventType.UPDATE;
import static org.hibernate.internal.util.ReflectHelper.isAbstractClass;
import static org.hibernate.internal.util.StringHelper.isEmpty;
import static org.hibernate.internal.util.collections.ArrayHelper.contains;
import static org.hibernate.internal.util.collections.ArrayHelper.to2DStringArray;
@ -297,6 +299,7 @@ import static org.hibernate.internal.util.collections.CollectionHelper.toSmallLi
import static org.hibernate.metamodel.RepresentationMode.POJO;
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.discriminatorLiteral;
import static org.hibernate.pretty.MessageHelper.infoString;
import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey;
@ -452,7 +455,7 @@ public abstract class AbstractEntityPersister
protected ReflectionOptimizer.AccessOptimizer accessOptimizer;
private final String[] fullDiscriminatorSQLValues;
// private final String[] fullDiscriminatorSQLValues;
private final Object[] fullDiscriminatorValues;
/**
@ -800,36 +803,36 @@ public abstract class AbstractEntityPersister
&& shouldInvalidateCache( bootDescriptor, creationContext );
final List<Object> values = new ArrayList<>();
final List<String> sqlValues = new ArrayList<>();
// final List<String> sqlValues = new ArrayList<>();
if ( bootDescriptor.isPolymorphic() && bootDescriptor.getDiscriminator() != null ) {
if ( !getEntityMetamodel().isAbstract() ) {
Object discriminatorValue = DiscriminatorHelper.getDiscriminatorValue( bootDescriptor );
String discriminatorSQLValue = DiscriminatorHelper.getDiscriminatorSQLValue( bootDescriptor, dialect, factory );
values.add( discriminatorValue );
sqlValues.add( discriminatorSQLValue );
values.add( DiscriminatorHelper.getDiscriminatorValue( bootDescriptor ) );
// sqlValues.add( DiscriminatorHelper.getDiscriminatorSQLValue( bootDescriptor, dialect, factory ) );
}
final List<Subclass> subclasses = bootDescriptor.getSubclasses();
for ( int k = 0; k < subclasses.size(); k++ ) {
Subclass subclass = subclasses.get( k );
final Subclass subclass = subclasses.get( k );
//copy/paste from EntityMetamodel:
boolean subclassAbstract = subclass.isAbstract() == null
? subclass.hasPojoRepresentation() && ReflectHelper.isAbstractClass( subclass.getMappedClass() )
: subclass.isAbstract();
if ( !subclassAbstract ) {
Object subclassDiscriminatorValue = DiscriminatorHelper.getDiscriminatorValue( subclass );
values.add( subclassDiscriminatorValue );
sqlValues.add( DiscriminatorHelper.getDiscriminatorSQLValue( subclass, dialect, factory ) );
if ( !isAbstract( subclass ) ) {
values.add( DiscriminatorHelper.getDiscriminatorValue( subclass ) );
// sqlValues.add( DiscriminatorHelper.getDiscriminatorSQLValue( subclass, dialect, factory ) );
}
}
}
fullDiscriminatorSQLValues = toStringArray( sqlValues );
// fullDiscriminatorSQLValues = toStringArray( sqlValues );
fullDiscriminatorValues = toObjectArray( values );
}
static boolean isAbstract(PersistentClass subclass) {
final Boolean knownAbstract = subclass.isAbstract();
return knownAbstract == null
? subclass.hasPojoRepresentation() && isAbstractClass( subclass.getMappedClass() )
: knownAbstract;
}
private boolean shouldUseReferenceCacheEntries() {
// Check if we can use Reference Cached entities in 2lc
// todo : should really validate that the cache access type is read-only
@ -2225,12 +2228,9 @@ public abstract class AbstractEntityPersister
String[] templates = getSubclassPropertyFormulaTemplateClosure()[i];
String[] result = new String[cols.length];
for ( int j = 0; j < cols.length; j++ ) {
if ( cols[j] == null ) {
result[j] = StringHelper.replace( templates[j], Template.TEMPLATE, alias );
}
else {
result[j] = StringHelper.qualify( alias, cols[j] );
}
result[j] = cols[j] == null
? StringHelper.replace( templates[j], Template.TEMPLATE, alias )
: StringHelper.qualify( alias, cols[j] );
}
return result;
}
@ -2927,6 +2927,8 @@ public abstract class AbstractEntityPersister
}
}
public abstract Map<Object, String> getSubclassByDiscriminatorValue();
protected abstract boolean needsDiscriminator();
protected boolean isDiscriminatorFormula() {
@ -4929,7 +4931,7 @@ public abstract class AbstractEntityPersister
else {
rowIdMapping = creationProcess.processSubPart(
rowIdName,
(role, process) -> new EntityRowIdMappingImpl( rowIdName, this.getTableName(), this )
(role, process) -> new EntityRowIdMappingImpl( rowIdName, getTableName(), this )
);
}
@ -5064,7 +5066,7 @@ public abstract class AbstractEntityPersister
protected EntityDiscriminatorMapping generateDiscriminatorMapping(
PersistentClass bootEntityDescriptor,
MappingModelCreationProcess modelCreationProcess) {
if ( getDiscriminatorType() == null) {
if ( getDiscriminatorType() == null ) {
return null;
}
else {
@ -5074,7 +5076,7 @@ public abstract class AbstractEntityPersister
final Integer precision;
final Integer scale;
if ( getDiscriminatorFormulaTemplate() == null ) {
Column column = bootEntityDescriptor.getDiscriminator() == null
final Column column = bootEntityDescriptor.getDiscriminator() == null
? null
: bootEntityDescriptor.getDiscriminator().getColumns().get( 0 );
discriminatorColumnExpression = getDiscriminatorColumnReaders();
@ -5098,7 +5100,7 @@ public abstract class AbstractEntityPersister
precision = null;
scale = null;
}
return new ExplicitColumnDiscriminatorMappingImpl (
return new ExplicitColumnDiscriminatorMappingImpl(
this,
getTableName(),
discriminatorColumnExpression,
@ -5106,16 +5108,38 @@ public abstract class AbstractEntityPersister
isPhysicalDiscriminator(),
columnDefinition, length, precision, scale,
(DiscriminatorType<?>) getTypeDiscriminatorMetadata().getResolutionType(),
buildDiscriminatorValueMappings( bootEntityDescriptor, modelCreationProcess ),
buildDiscriminatorValueMappings( modelCreationProcess ),
modelCreationProcess
);
}
}
protected abstract Map<Object, DiscriminatorValueDetails> buildDiscriminatorValueMappings(
PersistentClass bootEntityDescriptor,
MappingModelCreationProcess modelCreationProcess);
@Override
public abstract BasicType<?> getDiscriminatorType();
protected Map<Object, DiscriminatorValueDetails> buildDiscriminatorValueMappings(
MappingModelCreationProcess modelCreationProcess) {
final MappingMetamodelImplementor mappingModel = modelCreationProcess.getCreationContext()
.getSessionFactory()
.getMappingMetamodel();
//noinspection unchecked
final JdbcLiteralFormatter<Object> jdbcLiteralFormatter =
(JdbcLiteralFormatter<Object>) getDiscriminatorType().getJdbcLiteralFormatter();
final Dialect dialect = modelCreationProcess.getCreationContext()
.getSessionFactory().getJdbcServices().getDialect();
final Map<Object, DiscriminatorValueDetails> valueMappings = new ConcurrentHashMap<>();
getSubclassByDiscriminatorValue().forEach( (value, entityName) -> {
final DiscriminatorValueDetailsImpl valueMapping = new DiscriminatorValueDetailsImpl(
value,
discriminatorLiteral( jdbcLiteralFormatter, dialect, value ),
mappingModel.findEntityDescriptor( entityName )
);
valueMappings.put( value, valueMapping );
} );
return valueMappings;
}
protected EntityVersionMapping generateVersionMapping(
Supplier<?> templateInstanceCreator,

View File

@ -38,10 +38,7 @@ public class DiscriminatorHelper {
}
}
static String getDiscriminatorSQLValue(
PersistentClass persistentClass,
Dialect dialect,
SessionFactoryImplementor factory) {
static String getDiscriminatorSQLValue(PersistentClass persistentClass, Dialect dialect) {
if ( persistentClass.isDiscriminatorValueNull() ) {
return InFragment.NULL;
}
@ -49,11 +46,7 @@ public class DiscriminatorHelper {
return InFragment.NOT_NULL;
}
else {
return discriminatorSqlLiteral(
getDiscriminatorType( persistentClass ),
persistentClass,
dialect
);
return discriminatorSqlLiteral( getDiscriminatorType( persistentClass ), persistentClass, dialect );
}
}
@ -62,7 +55,7 @@ public class DiscriminatorHelper {
try {
return discriminatorType.getJavaTypeDescriptor().fromString( persistentClass.getDiscriminatorValue() );
}
catch (Exception e) {
catch ( Exception e ) {
throw new MappingException( "Could not parse discriminator value", e );
}
}
@ -90,7 +83,7 @@ public class DiscriminatorHelper {
);
}
public static <T> String jdbcLiteral(
private static <T> String jdbcLiteral(
T value,
JdbcLiteralFormatter<T> formatter,
Dialect dialect) {
@ -101,4 +94,11 @@ public class DiscriminatorHelper {
throw new MappingException( "Could not format discriminator value to SQL string", e );
}
}
static String discriminatorLiteral(JdbcLiteralFormatter<Object> formatter, Dialect dialect, Object value) {
return value == NULL_DISCRIMINATOR || value == NOT_NULL_DISCRIMINATOR
? null
: jdbcLiteral( value, formatter, dialect );
}
}

View File

@ -14,7 +14,6 @@ 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;
@ -29,7 +28,6 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.DynamicFilterAliasGenerator;
import org.hibernate.internal.FilterAliasGenerator;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.jdbc.Expectation;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.Formula;
@ -43,7 +41,6 @@ import org.hibernate.mapping.Subclass;
import org.hibernate.mapping.Table;
import org.hibernate.mapping.Value;
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.EntityVersionMapping;
@ -71,13 +68,15 @@ 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;
import static java.util.Collections.emptyMap;
import static org.hibernate.internal.util.collections.ArrayHelper.to2DStringArray;
import static org.hibernate.internal.util.collections.ArrayHelper.toIntArray;
import static org.hibernate.internal.util.collections.ArrayHelper.toStringArray;
import static org.hibernate.internal.util.collections.CollectionHelper.linkedMapOfSize;
import static org.hibernate.internal.util.collections.CollectionHelper.mapOfSize;
import static org.hibernate.jdbc.Expectations.appropriateExpectation;
import static org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper.buildEncapsulatedCompositeIdentifierMapping;
import static org.hibernate.persister.entity.DiscriminatorHelper.NOT_NULL_DISCRIMINATOR;
@ -143,6 +142,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
// values in the outer join using an SQL CASE
private final Map<Object,String> subclassesByDiscriminatorValue = new HashMap<>();
private final String[] discriminatorValues;
private final boolean[] discriminatorAbstract;
private final String[] notNullColumnNames;
private final int[] notNullColumnTableNumbers;
@ -210,7 +210,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
}
discriminatorType = DiscriminatorHelper.getDiscriminatorType( persistentClass );
discriminatorValue = DiscriminatorHelper.getDiscriminatorValue( persistentClass );
discriminatorSQLString = DiscriminatorHelper.getDiscriminatorSQLValue( persistentClass, dialect, factory );
discriminatorSQLString = DiscriminatorHelper.getDiscriminatorSQLValue( persistentClass, dialect );
}
else {
explicitDiscriminatorColumnName = null;
@ -528,8 +528,8 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
}
}
subclassColumnTableNumberClosure = ArrayHelper.toIntArray( columnTableNumbers );
subclassPropertyTableNumberClosure = ArrayHelper.toIntArray( propTableNumbers );
subclassColumnTableNumberClosure = toIntArray( columnTableNumbers );
subclassPropertyTableNumberClosure = toIntArray( propTableNumbers );
// subclassFormulaTableNumberClosure = ArrayHelper.toIntArray( formulaTableNumbers );
subclassColumnClosure = toStringArray( columns );
@ -544,19 +544,21 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
discriminatorValuesByTableName = emptyMap();
discriminatorColumnNameByTableName = emptyMap();
discriminatorValues = null;
discriminatorAbstract = null;
notNullColumnTableNumbers = null;
notNullColumnNames = null;
}
else {
subclassesByDiscriminatorValue.put( discriminatorValue, getEntityName() );
discriminatorValuesByTableName = CollectionHelper.linkedMapOfSize( subclassSpan + 1 );
discriminatorColumnNameByTableName = CollectionHelper.linkedMapOfSize( subclassSpan + 1 );
subclassNameByTableName = CollectionHelper.mapOfSize( subclassSpan + 1 );
discriminatorValuesByTableName = linkedMapOfSize( subclassSpan + 1 );
discriminatorColumnNameByTableName = linkedMapOfSize( subclassSpan + 1 );
subclassNameByTableName = mapOfSize( subclassSpan + 1 );
Table table = persistentClass.getTable();
discriminatorValues = new String[subclassSpan];
initDiscriminatorProperties( dialect, subclassSpanMinusOne, table, discriminatorValue );
discriminatorAbstract = new boolean[subclassSpan];
initDiscriminatorProperties( dialect, subclassSpanMinusOne, table, discriminatorValue, isAbstract( persistentClass) );
notNullColumnTableNumbers = new int[subclassSpan];
final int id = getTableId(
@ -580,7 +582,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
// persisters for a class hierarchy, so that the use of
// "foo.class = Bar" works in HQL
: subclass.getSubclassId();
initDiscriminatorProperties( dialect, k, subclassTable, discriminatorValue );
initDiscriminatorProperties( dialect, k, subclassTable, discriminatorValue, isAbstract( subclass ) );
subclassesByDiscriminatorValue.put( discriminatorValue, subclass.getEntityName() );
int tableId = getTableId(
subclassTable.getQualifiedName( factory.getSqlStringGenerationContext() ),
@ -600,12 +602,18 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
}
private void initDiscriminatorProperties(Dialect dialect, int k, Table table, Object discriminatorValue) {
private void initDiscriminatorProperties(Dialect dialect, int k, Table table, Object discriminatorValue, boolean isAbstract) {
final String tableName = determineTableName( table );
final String columnName = table.getPrimaryKey().getColumn( 0 ).getQuotedName( dialect );
discriminatorValuesByTableName.put( tableName, discriminatorValue );
discriminatorColumnNameByTableName.put( tableName, columnName );
discriminatorValues[k] = discriminatorValue.toString();
discriminatorAbstract[k] = isAbstract;
}
@Override
public Map<Object, String> getSubclassByDiscriminatorValue() {
return subclassesByDiscriminatorValue;
}
/**
@ -815,7 +823,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
}
@Override
public Type getDiscriminatorType() {
public BasicType<?> getDiscriminatorType() {
return discriminatorType;
}
@ -862,35 +870,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
}
}
@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
public void addDiscriminatorToInsertGroup(MutationGroupBuilder insertGroupBuilder) {
if ( explicitDiscriminatorColumnName != null ) {
@ -1265,32 +1244,34 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
if ( superMappingType != null ) {
return superMappingType.getDiscriminatorMapping();
}
if ( hasSubclasses() ) {
else if ( hasSubclasses() ) {
final String formula = getDiscriminatorFormulaTemplate();
if ( explicitDiscriminatorColumnName != null || formula != null ) {
// even though this is a joined-hierarchy the user has defined an
// even though this is a JOINED hierarchy the user has defined an
// explicit discriminator column - so we can use the normal
// discriminator mapping
return super.generateDiscriminatorMapping( bootEntityDescriptor, modelCreationProcess );
}
// otherwise, we need to use the case-statement approach
else {
// otherwise, we need to use the case approach
return new CaseStatementDiscriminatorMappingImpl(
this,
subclassTableNameClosure,
notNullColumnTableNumbers,
notNullColumnNames,
discriminatorValues,
discriminatorAbstract,
subclassNameByTableName,
(DiscriminatorType<?>) getTypeDiscriminatorMetadata().getResolutionType(),
buildDiscriminatorValueMappings( bootEntityDescriptor, modelCreationProcess ),
buildDiscriminatorValueMappings( modelCreationProcess ),
modelCreationProcess
);
}
}
else {
return null;
}
}
@Override
protected EntityIdentifierMapping generateNonEncapsulatedCompositeIdentifierMapping(

View File

@ -12,7 +12,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
@ -35,10 +34,8 @@ 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;
@ -49,8 +46,6 @@ import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.model.ast.builder.MutationGroupBuilder;
import org.hibernate.sql.model.ast.builder.TableInsertBuilder;
import org.hibernate.type.BasicType;
import org.hibernate.type.Type;
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
import static org.hibernate.internal.util.collections.ArrayHelper.to2DStringArray;
import static org.hibernate.internal.util.collections.ArrayHelper.toBooleanArray;
@ -324,7 +319,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
SqmFunctionRegistry functionRegistry = factory.getQueryEngine().getSqmFunctionRegistry();
discriminatorType = DiscriminatorHelper.getDiscriminatorType( persistentClass );
discriminatorValue = DiscriminatorHelper.getDiscriminatorValue( persistentClass );
discriminatorSQLValue = DiscriminatorHelper.getDiscriminatorSQLValue( persistentClass, dialect, factory );
discriminatorSQLValue = DiscriminatorHelper.getDiscriminatorSQLValue( persistentClass, dialect );
discriminatorInsertable = isDiscriminatorInsertable( persistentClass );
if ( discriminator.hasFormula() ) {
Formula formula = (Formula) selectable;
@ -484,10 +479,15 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
}
@Override
public Type getDiscriminatorType() {
public BasicType<?> getDiscriminatorType() {
return discriminatorType;
}
@Override
public Map<Object, String> getSubclassByDiscriminatorValue() {
return subclassesByDiscriminatorValue;
}
@Override
public TableDetails getMappedTableDetails() {
return getTableMapping( 0 );
@ -668,36 +668,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
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
public String[] getConstraintOrderedTableNameClosure() {
return constraintOrderedTableNames;

View File

@ -17,7 +17,6 @@ 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;
@ -63,8 +62,6 @@ import org.hibernate.sql.ast.tree.from.UnionTableReference;
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
@ -306,10 +303,15 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
}
@Override
public Type getDiscriminatorType() {
public BasicType<?> getDiscriminatorType() {
return discriminatorType;
}
@Override
public Map<Object, String> getSubclassByDiscriminatorValue() {
return subclassByDiscriminatorValue;
}
@Override
public TableDetails getMappedTableDetails() {
return getTableMapping( 0 );
@ -335,29 +337,6 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
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
public Serializable[] getPropertySpaces() {
return spaces;

View File

@ -34,9 +34,7 @@ import org.hibernate.generator.Generator;
import org.hibernate.generator.OnExecutionGenerator;
import org.hibernate.generator.BeforeExecutionGenerator;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.GeneratorCreator;
import org.hibernate.mapping.PersistentClass;
@ -58,6 +56,11 @@ import org.hibernate.type.ManyToOneType;
import org.hibernate.type.Type;
import static org.hibernate.internal.CoreLogging.messageLogger;
import static org.hibernate.internal.util.ReflectHelper.isAbstractClass;
import static org.hibernate.internal.util.ReflectHelper.isFinalClass;
import static org.hibernate.internal.util.collections.ArrayHelper.toIntArray;
import static org.hibernate.internal.util.collections.CollectionHelper.toSmallMap;
import static org.hibernate.internal.util.collections.CollectionHelper.toSmallSet;
/**
* Centralizes metamodel information about an entity.
@ -365,16 +368,16 @@ public class EntityMetamodel implements Serializable {
mutableIndexes.set( i );
}
mapPropertyToIndex(property, i);
mapPropertyToIndex( property, i );
}
if (naturalIdNumbers.size()==0) {
if ( naturalIdNumbers.isEmpty() ) {
naturalIdPropertyNumbers = null;
hasImmutableNaturalId = false;
hasCacheableNaturalId = false;
}
else {
naturalIdPropertyNumbers = ArrayHelper.toIntArray(naturalIdNumbers);
naturalIdPropertyNumbers = toIntArray( naturalIdNumbers );
hasImmutableNaturalId = !foundUpdateableNaturalIdProperty;
hasCacheableNaturalId = persistentClass.getNaturalIdCacheRegionName() != null;
}
@ -392,25 +395,26 @@ public class EntityMetamodel implements Serializable {
versionPropertyIndex = tempVersionProperty;
hasLazyProperties = hasLazy;
if ( hasLazyProperties ) {
LOG.lazyPropertyFetchingAvailable(name);
LOG.lazyPropertyFetchingAvailable( name );
}
lazy = persistentClass.isLazy() && (
// TODO: this disables laziness even in non-pojo entity modes:
!persistentClass.hasPojoRepresentation() ||
!ReflectHelper.isFinalClass( persistentClass.getProxyInterface() )
!isFinalClass( persistentClass.getProxyInterface() )
);
mutable = persistentClass.isMutable();
if ( persistentClass.isAbstract() == null ) {
// legacy behavior (with no abstract attribute specified)
isAbstract = persistentClass.hasPojoRepresentation() &&
ReflectHelper.isAbstractClass( persistentClass.getMappedClass() );
isAbstract = persistentClass.hasPojoRepresentation()
&& isAbstractClass( persistentClass.getMappedClass() );
}
else {
isAbstract = persistentClass.isAbstract();
if ( !isAbstract && persistentClass.hasPojoRepresentation() &&
ReflectHelper.isAbstractClass( persistentClass.getMappedClass() ) ) {
LOG.entityMappedAsNonAbstract(name);
if ( !isAbstract
&& persistentClass.hasPojoRepresentation()
&& isAbstractClass( persistentClass.getMappedClass() ) ) {
LOG.entityMappedAsNonAbstract( name );
}
}
@ -447,7 +451,7 @@ public class EntityMetamodel implements Serializable {
subclassEntityNamesLocal.add( subclass.getEntityName() );
}
subclassEntityNamesLocal.add( name );
subclassEntityNames = CollectionHelper.toSmallSet( subclassEntityNamesLocal );
subclassEntityNames = toSmallSet( subclassEntityNamesLocal );
HashMap<Class<?>, String> entityNameByInheritanceClassMapLocal = new HashMap<>();
if ( persistentClass.hasPojoRepresentation() ) {
@ -456,7 +460,7 @@ public class EntityMetamodel implements Serializable {
entityNameByInheritanceClassMapLocal.put( subclass.getMappedClass(), subclass.getEntityName() );
}
}
entityNameByInheritanceClassMap = CollectionHelper.toSmallMap( entityNameByInheritanceClassMapLocal );
entityNameByInheritanceClassMap = toSmallMap( entityNameByInheritanceClassMapLocal );
}
private static boolean generatedWithNoParameter(Generator generator) {
@ -738,7 +742,7 @@ public class EntityMetamodel implements Serializable {
@Override
public String toString() {
return "EntityMetamodel(" + name + ':' + ArrayHelper.toString(properties) + ')';
return "EntityMetamodel(" + name + ':' + ArrayHelper.toString( properties ) + ')';
}
// temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -13,6 +13,8 @@ import java.util.List;
import static jakarta.persistence.CascadeType.ALL;
import static jakarta.persistence.InheritanceType.JOINED;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertNotNull;
import static junit.framework.TestCase.assertNull;
import static junit.framework.TestCase.assertTrue;
import static org.hibernate.cfg.AvailableSettings.FORMAT_SQL;
import static org.hibernate.cfg.AvailableSettings.SHOW_SQL;
@ -20,7 +22,7 @@ import static org.hibernate.cfg.AvailableSettings.SHOW_SQL;
public class RepeatedTableTest extends BaseCoreFunctionalTestCase {
@Override
protected Class[] getAnnotatedClasses() {
protected Class<?>[] getAnnotatedClasses() {
return new Class[]{
DataType.class,
ObjectType.class,
@ -81,6 +83,9 @@ public class RepeatedTableTest extends BaseCoreFunctionalTestCase {
}
try (Session sess = openSession()) {
SimpleType simpleType = sess.find(SimpleType.class, sId);
assertNotNull( simpleType );
SimpleType wrongType = sess.find(SimpleType.class, id);
assertNull( wrongType );
}
try (Session sess = openSession()) {