HHH-14526 tolerate dupe tables in JOINED inheritance with discriminator
and also support @DiscriminatorOptions for JOINED inheritance
This commit is contained in:
parent
4946e8ca45
commit
2355f98586
|
@ -63,11 +63,7 @@ public class InformixSqmToSqlAstConverter<T extends Statement> extends BaseSqmTo
|
|||
null,
|
||||
null,
|
||||
null,
|
||||
new NamedTableReference(
|
||||
"(select 1)",
|
||||
"dummy_(x)",
|
||||
false
|
||||
),
|
||||
new NamedTableReference( "(select 1)", "dummy_(x)" ),
|
||||
null,
|
||||
getCreationContext().getSessionFactory()
|
||||
)
|
||||
|
|
|
@ -63,11 +63,7 @@ public class IngresSqmToSqlAstConverter<T extends Statement> extends BaseSqmToSq
|
|||
null,
|
||||
null,
|
||||
null,
|
||||
new NamedTableReference(
|
||||
"(select 1)",
|
||||
"dummy_(x)",
|
||||
false
|
||||
),
|
||||
new NamedTableReference( "(select 1)", "dummy_(x)" ),
|
||||
null,
|
||||
getCreationContext().getSessionFactory()
|
||||
)
|
||||
|
|
|
@ -63,7 +63,7 @@ public class SybaseLegacySqmToSqlAstConverter<T extends Statement> extends BaseS
|
|||
null,
|
||||
null,
|
||||
null,
|
||||
new NamedTableReference( "(select 1)", "dummy_(x)", false ),
|
||||
new NamedTableReference( "(select 1)", "dummy_(x)" ),
|
||||
null,
|
||||
getCreationContext().getSessionFactory()
|
||||
)
|
||||
|
|
|
@ -19,7 +19,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|||
*
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
@Target({ TYPE })
|
||||
@Target(TYPE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface DiscriminatorOptions {
|
||||
/**
|
||||
|
@ -29,8 +29,8 @@ public @interface DiscriminatorOptions {
|
|||
* there are discriminator column values which do <em>not</em>
|
||||
* map to any subtype of the root entity type.
|
||||
*
|
||||
* @return {@code true} if allowd discriminator values must always
|
||||
* by explicitly enumerated
|
||||
* @return {@code true} if allowed discriminator values must always
|
||||
* be explicitly enumerated
|
||||
*/
|
||||
boolean force() default false;
|
||||
|
||||
|
|
|
@ -1886,13 +1886,13 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
|||
}
|
||||
|
||||
/**
|
||||
* Recursively builds a list of FkSecondPass instances ready to be processed in this order.
|
||||
* Recursively builds a list of {@link FkSecondPass} instances ready to be processed in this order.
|
||||
* Checking all dependencies recursively seems quite expensive, but the original code just relied
|
||||
* on some sort of table name sorting which failed in certain circumstances.
|
||||
* <p>
|
||||
* See {@code ANN-722} and {@code ANN-730}
|
||||
*
|
||||
* @param orderedFkSecondPasses The list containing the <code>FkSecondPass</code> instances ready
|
||||
* @param orderedFkSecondPasses The list containing the {@link FkSecondPass} instances ready
|
||||
* for processing.
|
||||
* @param isADependencyOf Our lookup data structure to determine dependencies between tables
|
||||
* @param startTable Table name to start recursive algorithm.
|
||||
|
@ -1905,15 +1905,13 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
|||
String currentTable) {
|
||||
Set<FkSecondPass> dependencies = isADependencyOf.get( currentTable );
|
||||
if ( dependencies != null ) {
|
||||
for ( FkSecondPass sp : dependencies ) {
|
||||
String dependentTable = sp.getValue().getTable().getQualifiedTableName().render();
|
||||
if ( dependentTable.compareTo( startTable ) == 0 ) {
|
||||
throw new AnnotationException( "Circular foreign key dependency involving tables '"
|
||||
+ startTable + "' and '" + dependentTable + "'" );
|
||||
for ( FkSecondPass pass : dependencies ) {
|
||||
String dependentTable = pass.getValue().getTable().getQualifiedTableName().render();
|
||||
if ( dependentTable.compareTo( startTable ) != 0 ) {
|
||||
buildRecursiveOrderedFkSecondPasses( orderedFkSecondPasses, isADependencyOf, startTable, dependentTable );
|
||||
}
|
||||
buildRecursiveOrderedFkSecondPasses( orderedFkSecondPasses, isADependencyOf, startTable, dependentTable );
|
||||
if ( !orderedFkSecondPasses.contains( sp ) ) {
|
||||
orderedFkSecondPasses.add( 0, sp );
|
||||
if ( !orderedFkSecondPasses.contains( pass ) ) {
|
||||
orderedFkSecondPasses.add( 0, pass );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -638,6 +638,7 @@ public class EntityBinder {
|
|||
}
|
||||
|
||||
private void singleTableInheritance(InheritanceState inheritanceState, PropertyHolder holder) {
|
||||
processDiscriminatorOptions();
|
||||
final AnnotatedDiscriminatorColumn discriminatorColumn = processSingleTableDiscriminatorProperties( inheritanceState );
|
||||
if ( !inheritanceState.hasParents() ) { // todo : sucks that this is separate from RootClass distinction
|
||||
if ( inheritanceState.hasSiblings()
|
||||
|
@ -648,10 +649,12 @@ public class EntityBinder {
|
|||
}
|
||||
|
||||
private void joinedInheritance(InheritanceState state, PersistentClass superEntity, PropertyHolder holder) {
|
||||
processDiscriminatorOptions();
|
||||
|
||||
if ( state.hasParents() ) {
|
||||
final AnnotatedJoinColumns joinColumns = subclassJoinColumns( annotatedClass, superEntity, context );
|
||||
final JoinedSubclass jsc = (JoinedSubclass) persistentClass;
|
||||
final DependantValue key = new DependantValue(context, jsc.getTable(), jsc.getIdentifier() );
|
||||
final DependantValue key = new DependantValue( context, jsc.getTable(), jsc.getIdentifier() );
|
||||
jsc.setKey( key );
|
||||
handleForeignKeys( annotatedClass, context, key );
|
||||
final OnDelete onDelete = annotatedClass.getAnnotation( OnDelete.class );
|
||||
|
@ -753,6 +756,14 @@ public class EntityBinder {
|
|||
}
|
||||
}
|
||||
|
||||
private void processDiscriminatorOptions() {
|
||||
final DiscriminatorOptions discriminatorOptions = annotatedClass.getAnnotation( DiscriminatorOptions.class );
|
||||
if ( discriminatorOptions != null ) {
|
||||
forceDiscriminator = discriminatorOptions.force();
|
||||
insertableDiscriminator = discriminatorOptions.insert();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process all discriminator-related metadata per rules for "single table" inheritance
|
||||
*/
|
||||
|
@ -775,12 +786,6 @@ public class EntityBinder {
|
|||
LOG.invalidDiscriminatorAnnotation( annotatedClass.getName() );
|
||||
}
|
||||
|
||||
final DiscriminatorOptions discriminatorOptions = annotatedClass.getAnnotation( DiscriminatorOptions.class );
|
||||
if ( discriminatorOptions != null ) {
|
||||
forceDiscriminator = discriminatorOptions.force();
|
||||
insertableDiscriminator = discriminatorOptions.insert();
|
||||
}
|
||||
|
||||
return discriminator;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,11 +63,7 @@ public class SybaseSqmToSqlAstConverter<T extends Statement> extends BaseSqmToSq
|
|||
null,
|
||||
null,
|
||||
null,
|
||||
new NamedTableReference(
|
||||
"(select 1)",
|
||||
"dummy_(x)",
|
||||
false
|
||||
),
|
||||
new NamedTableReference( "(select 1)", "dummy_(x)" ),
|
||||
null,
|
||||
getCreationContext().getSessionFactory()
|
||||
)
|
||||
|
|
|
@ -11,7 +11,6 @@ import java.util.HashSet;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.engine.OptimisticLockStyle;
|
||||
import org.hibernate.internal.FilterConfiguration;
|
||||
|
@ -242,14 +241,13 @@ public class Subclass extends PersistentClass {
|
|||
|
||||
@Override
|
||||
public boolean isJoinedSubclass() {
|
||||
return getTable()!=getRootTable();
|
||||
return getTable() != getRootTable();
|
||||
}
|
||||
|
||||
public void createForeignKey() {
|
||||
if ( !isJoinedSubclass() ) {
|
||||
throw new AssertionFailure( "not a joined-subclass" );
|
||||
if ( isJoinedSubclass() ) {
|
||||
getKey().createForeignKeyOfEntity( getSuperclass().getEntityName() );
|
||||
}
|
||||
getKey().createForeignKeyOfEntity( getSuperclass().getEntityName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -111,6 +111,7 @@ 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;
|
||||
|
@ -234,6 +235,7 @@ import org.hibernate.sql.ast.tree.expression.AliasedExpression;
|
|||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
|
||||
import org.hibernate.sql.ast.tree.from.NamedTableReference;
|
||||
import org.hibernate.sql.ast.tree.from.StandardTableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
|
@ -241,7 +243,10 @@ import org.hibernate.sql.ast.tree.from.TableReference;
|
|||
import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
|
||||
import org.hibernate.sql.ast.tree.insert.InsertSelectStatement;
|
||||
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.InListPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.Junction;
|
||||
import org.hibernate.sql.ast.tree.predicate.NegatedPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.NullnessPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectClause;
|
||||
|
@ -271,6 +276,7 @@ import org.hibernate.type.Type;
|
|||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.java.MutabilityPlan;
|
||||
|
||||
import static java.util.Collections.emptySet;
|
||||
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
|
||||
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable;
|
||||
import static org.hibernate.engine.internal.ManagedTypeHelper.processIfPersistentAttributeInterceptable;
|
||||
|
@ -278,7 +284,20 @@ 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.StringHelper.isEmpty;
|
||||
import static org.hibernate.internal.util.collections.ArrayHelper.contains;
|
||||
import static org.hibernate.internal.util.collections.ArrayHelper.to2DStringArray;
|
||||
import static org.hibernate.internal.util.collections.ArrayHelper.toBooleanArray;
|
||||
import static org.hibernate.internal.util.collections.ArrayHelper.toIntArray;
|
||||
import static org.hibernate.internal.util.collections.ArrayHelper.toObjectArray;
|
||||
import static org.hibernate.internal.util.collections.ArrayHelper.toStringArray;
|
||||
import static org.hibernate.internal.util.collections.ArrayHelper.toTypeArray;
|
||||
import static org.hibernate.internal.util.collections.CollectionHelper.isNotEmpty;
|
||||
import static org.hibernate.internal.util.collections.CollectionHelper.toSmallList;
|
||||
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.pretty.MessageHelper.infoString;
|
||||
import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey;
|
||||
|
||||
/**
|
||||
|
@ -433,6 +452,9 @@ public abstract class AbstractEntityPersister
|
|||
|
||||
protected ReflectionOptimizer.AccessOptimizer accessOptimizer;
|
||||
|
||||
private final String[] fullDiscriminatorSQLValues;
|
||||
private final Object[] fullDiscriminatorValues;
|
||||
|
||||
/**
|
||||
* Warning:
|
||||
* When there are duplicated property names in the subclasses
|
||||
|
@ -524,12 +546,10 @@ public abstract class AbstractEntityPersister
|
|||
final NamedQueryMemento namedQueryMemento = factory.getQueryEngine().getNamedObjectRepository()
|
||||
.resolve( factory, creationContext.getBootModel(), bootDescriptor.getLoaderName() );
|
||||
if ( namedQueryMemento == null ) {
|
||||
throw new IllegalArgumentException( "Could not resolve named load-query [" + getEntityName() + "] : " + bootDescriptor.getLoaderName() );
|
||||
throw new IllegalArgumentException( "Could not resolve named load-query [" + getEntityName()
|
||||
+ "] : " + bootDescriptor.getLoaderName() );
|
||||
}
|
||||
singleIdEntityLoader = new SingleIdEntityLoaderProvidedQueryImpl<>(
|
||||
this,
|
||||
namedQueryMemento
|
||||
);
|
||||
singleIdEntityLoader = new SingleIdEntityLoaderProvidedQueryImpl<>(this, namedQueryMemento );
|
||||
}
|
||||
else if ( batchSize > 1 ) {
|
||||
singleIdEntityLoader = createBatchingIdEntityLoader( this, batchSize, factory );
|
||||
|
@ -558,12 +578,12 @@ public abstract class AbstractEntityPersister
|
|||
// VERSION
|
||||
|
||||
versionColumnName = bootDescriptor.isVersioned()
|
||||
? bootDescriptor.getVersion().getColumns().get(0).getQuotedName(dialect)
|
||||
? bootDescriptor.getVersion().getColumns().get(0).getQuotedName( dialect )
|
||||
: null;
|
||||
|
||||
//WHERE STRING
|
||||
|
||||
if ( StringHelper.isEmpty( bootDescriptor.getWhere() ) ) {
|
||||
if ( isEmpty( bootDescriptor.getWhere() ) ) {
|
||||
sqlWhereStringTableExpression = null;
|
||||
sqlWhereStringTemplate = null;
|
||||
}
|
||||
|
@ -576,7 +596,7 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
containingClass = superclass;
|
||||
}
|
||||
this.sqlWhereStringTableExpression = determineTableName( containingClass.getTable() );
|
||||
sqlWhereStringTableExpression = determineTableName( containingClass.getTable() );
|
||||
sqlWhereStringTemplate = Template.renderWhereStringTemplate(
|
||||
"(" + bootDescriptor.getWhere() + ")",
|
||||
dialect,
|
||||
|
@ -670,12 +690,12 @@ public abstract class AbstractEntityPersister
|
|||
lobPropertiesLocalCollector.add( i );
|
||||
}
|
||||
}
|
||||
this.lobProperties = CollectionHelper.toSmallList( lobPropertiesLocalCollector );
|
||||
lobProperties = toSmallList( lobPropertiesLocalCollector );
|
||||
hasFormulaProperties = foundFormula;
|
||||
lazyPropertyColumnAliases = ArrayHelper.to2DStringArray( lazyColAliases );
|
||||
lazyPropertyNames = ArrayHelper.toStringArray( lazyNames );
|
||||
lazyPropertyNumbers = ArrayHelper.toIntArray( lazyNumbers );
|
||||
lazyPropertyTypes = ArrayHelper.toTypeArray( lazyTypes );
|
||||
lazyPropertyColumnAliases = to2DStringArray( lazyColAliases );
|
||||
lazyPropertyNames = toStringArray( lazyNames );
|
||||
lazyPropertyNumbers = toIntArray( lazyNumbers );
|
||||
lazyPropertyTypes = toTypeArray( lazyTypes );
|
||||
|
||||
// SUBCLASS PROPERTY CLOSURE
|
||||
final ArrayList<String> aliases = new ArrayList<>();
|
||||
|
@ -744,16 +764,16 @@ public abstract class AbstractEntityPersister
|
|||
joinedFetchesList.add( prop.getValue().getFetchMode() );
|
||||
cascades.add( prop.getCascadeStyle() );
|
||||
}
|
||||
subclassColumnAliasClosure = ArrayHelper.toStringArray( aliases );
|
||||
subclassFormulaAliasClosure = ArrayHelper.toStringArray( formulaAliases );
|
||||
subclassColumnAliasClosure = toStringArray( aliases );
|
||||
subclassFormulaAliasClosure = toStringArray( formulaAliases );
|
||||
|
||||
subclassPropertyNameClosure = ArrayHelper.toStringArray( names );
|
||||
subclassPropertyTypeClosure = ArrayHelper.toTypeArray( types );
|
||||
subclassPropertyNullabilityClosure = ArrayHelper.toBooleanArray( propNullables );
|
||||
subclassPropertyFormulaTemplateClosure = ArrayHelper.to2DStringArray( templates );
|
||||
subclassPropertyColumnNameClosure = ArrayHelper.to2DStringArray( propColumns );
|
||||
subclassPropertyColumnReaderClosure = ArrayHelper.to2DStringArray( propColumnReaders );
|
||||
subclassPropertyColumnReaderTemplateClosure = ArrayHelper.to2DStringArray( propColumnReaderTemplates );
|
||||
subclassPropertyNameClosure = toStringArray( names );
|
||||
subclassPropertyTypeClosure = toTypeArray( types );
|
||||
subclassPropertyNullabilityClosure = toBooleanArray( propNullables );
|
||||
subclassPropertyFormulaTemplateClosure = to2DStringArray( templates );
|
||||
subclassPropertyColumnNameClosure = to2DStringArray( propColumns );
|
||||
subclassPropertyColumnReaderClosure = to2DStringArray( propColumnReaders );
|
||||
subclassPropertyColumnReaderTemplateClosure = to2DStringArray( propColumnReaderTemplates );
|
||||
|
||||
subclassPropertyCascadeStyleClosure = new CascadeStyle[cascades.size()];
|
||||
int j = 0;
|
||||
|
@ -766,19 +786,48 @@ public abstract class AbstractEntityPersister
|
|||
subclassPropertyFetchModeClosure[j++] = fetchMode;
|
||||
}
|
||||
|
||||
propertyDefinedOnSubclass = ArrayHelper.toBooleanArray( definedBySubclass );
|
||||
propertyDefinedOnSubclass = toBooleanArray( definedBySubclass );
|
||||
|
||||
// Handle any filters applied to the class level
|
||||
filterHelper = CollectionHelper.isNotEmpty( bootDescriptor.getFilters() )
|
||||
? new FilterHelper(bootDescriptor.getFilters(), factory)
|
||||
filterHelper = isNotEmpty( bootDescriptor.getFilters() )
|
||||
? new FilterHelper( bootDescriptor.getFilters(), factory )
|
||||
: null;
|
||||
|
||||
useReferenceCacheEntries = shouldUseReferenceCacheEntries();
|
||||
cacheEntryHelper = buildCacheEntryHelper();
|
||||
invalidateCache = sessionFactoryOptions.isSecondLevelCacheEnabled()
|
||||
&& canWriteToCache
|
||||
&& shouldInvalidateCache(bootDescriptor, creationContext);
|
||||
&& shouldInvalidateCache( bootDescriptor, creationContext );
|
||||
|
||||
final List<Object> values = 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 );
|
||||
}
|
||||
|
||||
final List<Subclass> subclasses = bootDescriptor.getSubclasses();
|
||||
for ( int k = 0; k < subclasses.size(); k++ ) {
|
||||
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 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fullDiscriminatorSQLValues = toStringArray( sqlValues );
|
||||
fullDiscriminatorValues = toObjectArray( values );
|
||||
}
|
||||
|
||||
private boolean shouldUseReferenceCacheEntries() {
|
||||
|
@ -815,20 +864,18 @@ public abstract class AbstractEntityPersister
|
|||
protected abstract boolean isClassOrSuperclassTable(int j);
|
||||
|
||||
protected boolean isClassOrSuperclassJoin(int j) {
|
||||
/*
|
||||
* TODO:
|
||||
* SingleTableEntityPersister incorrectly used isClassOrSuperclassJoin == isClassOrSuperclassTable,
|
||||
* this caused HHH-12895, as this resulted in the subclass tables always being joined, even if no
|
||||
* property on these tables was accessed.
|
||||
*
|
||||
* JoinedTableEntityPersister does not use isClassOrSuperclassJoin at all, probably incorrectly so.
|
||||
* I however haven't been able to reproduce any quirks regarding <join>s, secondary tables or
|
||||
* @JoinTable's.
|
||||
*
|
||||
* Probably this method needs to be properly implemented for the various entity persisters,
|
||||
* but this at least fixes the SingleTableEntityPersister, while maintaining the previous
|
||||
* behaviour for other persisters.
|
||||
*/
|
||||
// TODO:
|
||||
// SingleTableEntityPersister incorrectly used isClassOrSuperclassJoin == isClassOrSuperclassTable,
|
||||
// this caused HHH-12895, as this resulted in the subclass tables always being joined, even if no
|
||||
// property on these tables was accessed.
|
||||
//
|
||||
// JoinedTableEntityPersister does not use isClassOrSuperclassJoin at all, probably incorrectly so.
|
||||
// I however haven't been able to reproduce any quirks regarding <join>s, secondary tables or
|
||||
// @JoinTable's.
|
||||
//
|
||||
// Probably this method needs to be properly implemented for the various entity persisters,
|
||||
// but this at least fixes the SingleTableEntityPersister, while maintaining the previous
|
||||
// behaviour for other persisters.
|
||||
return isClassOrSuperclassTable( j );
|
||||
}
|
||||
|
||||
|
@ -956,9 +1003,6 @@ public abstract class AbstractEntityPersister
|
|||
return tableNames;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private static SingleIdEntityLoader<?> createBatchingIdEntityLoader(
|
||||
EntityMappingType entityDescriptor,
|
||||
int batchSize,
|
||||
|
@ -989,7 +1033,7 @@ public abstract class AbstractEntityPersister
|
|||
// there is a risk of concurrent updates
|
||||
return true;
|
||||
}
|
||||
else if ( isCacheComplianceEnabled(creationContext) ) {
|
||||
else if ( isCacheComplianceEnabled( creationContext ) ) {
|
||||
// The JPA TCK (inadvertently, but still...)
|
||||
// requires that we cache entities with secondary
|
||||
// tables instead of being more careful and just
|
||||
|
@ -1066,9 +1110,8 @@ public abstract class AbstractEntityPersister
|
|||
|
||||
final LazyAttributesMetadata lazyAttributesMetadata = enhancementMetadata.getLazyAttributesMetadata();
|
||||
for ( String groupName : lazyAttributesMetadata.getFetchGroupNames() ) {
|
||||
final List<LazyAttributeDescriptor> fetchGroupAttributeDescriptors = lazyAttributesMetadata.getFetchGroupAttributeDescriptors(
|
||||
groupName
|
||||
);
|
||||
final List<LazyAttributeDescriptor> fetchGroupAttributeDescriptors =
|
||||
lazyAttributesMetadata.getFetchGroupAttributeDescriptors( groupName );
|
||||
final List<ModelPart> partsToSelect = new ArrayList<>( fetchGroupAttributeDescriptors.size() );
|
||||
|
||||
for ( LazyAttributeDescriptor lazyAttributeDescriptor : fetchGroupAttributeDescriptors ) {
|
||||
|
@ -1186,68 +1229,12 @@ public abstract class AbstractEntityPersister
|
|||
return naturalIdMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableGroup createRootTableGroup(
|
||||
boolean canUseInnerJoins,
|
||||
NavigablePath navigablePath,
|
||||
String explicitSourceAlias,
|
||||
Supplier<Consumer<Predicate>> additionalPredicateCollectorAccess,
|
||||
SqlAliasBase sqlAliasBase,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
FromClauseAccess fromClauseAccess,
|
||||
SqlAstCreationContext creationContext) {
|
||||
final TableReference primaryTableReference = createPrimaryTableReference(
|
||||
sqlAliasBase,
|
||||
sqlExpressionResolver,
|
||||
creationContext
|
||||
);
|
||||
|
||||
return new StandardTableGroup(
|
||||
canUseInnerJoins,
|
||||
navigablePath,
|
||||
this,
|
||||
explicitSourceAlias,
|
||||
primaryTableReference,
|
||||
true,
|
||||
sqlAliasBase,
|
||||
(tableExpression) -> ArrayHelper.contains( getSubclassTableNames(), tableExpression ),
|
||||
(tableExpression, tg) -> {
|
||||
final String[] subclassTableNames = getSubclassTableNames();
|
||||
for ( int i = 0; i < subclassTableNames.length; i++ ) {
|
||||
if ( tableExpression.equals( subclassTableNames[ i ] ) ) {
|
||||
final NamedTableReference joinedTableReference = new NamedTableReference(
|
||||
tableExpression,
|
||||
sqlAliasBase.generateNewAlias(),
|
||||
isNullableSubclassTable( i )
|
||||
);
|
||||
|
||||
return new TableReferenceJoin(
|
||||
shouldInnerJoinSubclassTable( i, Collections.emptySet() ),
|
||||
joinedTableReference,
|
||||
additionalPredicateCollectorAccess == null
|
||||
? null
|
||||
: generateJoinPredicate(
|
||||
primaryTableReference,
|
||||
joinedTableReference,
|
||||
getSubclassTableKeyColumns( i ),
|
||||
sqlExpressionResolver
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
getFactory()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference createPrimaryTableReference(
|
||||
SqlAliasBase sqlAliasBase,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
return resolvePrimaryTableReference( sqlAliasBase );
|
||||
return new NamedTableReference( getTableName(), sqlAliasBase.generateNewAlias() );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1265,7 +1252,7 @@ public abstract class AbstractEntityPersister
|
|||
lhs,
|
||||
joinTableExpression,
|
||||
sqlAliasBase,
|
||||
shouldInnerJoinSubclassTable( i, Collections.emptySet() ),
|
||||
shouldInnerJoinSubclassTable( i, emptySet() ),
|
||||
getSubclassTableKeyColumns( i ),
|
||||
sqlExpressionResolver
|
||||
);
|
||||
|
@ -1294,37 +1281,29 @@ public abstract class AbstractEntityPersister
|
|||
generateJoinPredicate(
|
||||
lhs,
|
||||
joinedTableReference,
|
||||
getKeyColumnNames(),
|
||||
targetColumns,
|
||||
sqlExpressionResolver
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected TableReference resolvePrimaryTableReference(SqlAliasBase sqlAliasBase) {
|
||||
return new NamedTableReference(
|
||||
getTableName(),
|
||||
sqlAliasBase.generateNewAlias(),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
protected Predicate generateJoinPredicate(
|
||||
TableReference rootTableReference,
|
||||
TableReference joinedTableReference,
|
||||
String[] pkColumnNames,
|
||||
String[] fkColumnNames,
|
||||
SqlExpressionResolver sqlExpressionResolver) {
|
||||
final EntityIdentifierMapping identifierMapping = getIdentifierMapping();
|
||||
|
||||
final Junction conjunction = new Junction( Junction.Nature.CONJUNCTION );
|
||||
|
||||
final String[] rootPkColumnNames = getKeyColumnNames();
|
||||
|
||||
assert rootPkColumnNames.length == fkColumnNames.length;
|
||||
assert rootPkColumnNames.length == identifierMapping.getJdbcTypeCount();
|
||||
assert pkColumnNames.length == fkColumnNames.length;
|
||||
assert pkColumnNames.length == identifierMapping.getJdbcTypeCount();
|
||||
|
||||
identifierMapping.forEachSelectable(
|
||||
(columnIndex, selection) -> {
|
||||
final String rootPkColumnName = rootPkColumnNames[ columnIndex ];
|
||||
final String rootPkColumnName = pkColumnNames[ columnIndex ];
|
||||
final Expression pkColumnExpression = sqlExpressionResolver.resolveSqlExpression(
|
||||
createColumnReferenceKey( rootTableReference, rootPkColumnName ),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
|
@ -1424,11 +1403,9 @@ public abstract class AbstractEntityPersister
|
|||
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
LOG.tracev(
|
||||
"Initializing lazy properties of: {0}, field access: {1}", MessageHelper.infoString(
|
||||
this,
|
||||
id,
|
||||
getFactory()
|
||||
), fieldName
|
||||
"Initializing lazy properties of: {0}, field access: {1}",
|
||||
infoString( this, id, getFactory() ),
|
||||
fieldName
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1465,12 +1442,13 @@ public abstract class AbstractEntityPersister
|
|||
return collectionType.getKeyOfOwner( owner, session );
|
||||
}
|
||||
|
||||
final EntityPersister ownerPersister = persister.getOwnerEntityPersister();
|
||||
if ( collectionType.getLHSPropertyName() == null ) {
|
||||
// collection key is defined by the owning entity identifier
|
||||
return persister.getOwnerEntityPersister().getIdentifier( owner, session );
|
||||
return ownerPersister.getIdentifier( owner, session );
|
||||
}
|
||||
else {
|
||||
return persister.getOwnerEntityPersister().getPropertyValue( owner, collectionType.getLHSPropertyName() );
|
||||
return ownerPersister.getPropertyValue( owner, collectionType.getLHSPropertyName() );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1525,7 +1503,6 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
|
||||
final Object selectedValue = values[i++];
|
||||
|
||||
final boolean set = initializeLazyProperty(
|
||||
fieldName,
|
||||
entity,
|
||||
|
@ -1544,10 +1521,10 @@ public abstract class AbstractEntityPersister
|
|||
|
||||
return result;
|
||||
}
|
||||
catch (JDBCException ex) {
|
||||
catch ( JDBCException ex ) {
|
||||
throw session.getJdbcServices().getSqlExceptionHelper().convert(
|
||||
ex.getSQLException(),
|
||||
"could not initialize lazy properties: " + MessageHelper.infoString( this, id, getFactory() ),
|
||||
"could not initialize lazy properties: " + infoString( this, id, getFactory() ),
|
||||
lazySelect.getJdbcSelect().getSqlString()
|
||||
);
|
||||
}
|
||||
|
@ -1575,11 +1552,7 @@ public abstract class AbstractEntityPersister
|
|||
// don't try to initialize the unfetched property
|
||||
}
|
||||
else {
|
||||
final Object propValue = lazyPropertyType.assemble(
|
||||
cachedValue,
|
||||
session,
|
||||
entity
|
||||
);
|
||||
final Object propValue = lazyPropertyType.assemble( cachedValue, session, entity );
|
||||
if ( initializeLazyProperty( fieldName, entity, entry, j, propValue ) ) {
|
||||
result = propValue;
|
||||
}
|
||||
|
@ -1954,7 +1927,7 @@ public abstract class AbstractEntityPersister
|
|||
);
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
LOG.trace(
|
||||
"Forcing version increment [" + MessageHelper.infoString( this, id, getFactory() ) + "; "
|
||||
"Forcing version increment [" + infoString( this, id, getFactory() ) + "; "
|
||||
+ getVersionType().toLoggableString( currentVersion, getFactory() ) + " -> "
|
||||
+ getVersionType().toLoggableString( nextVersion, getFactory() ) + "]"
|
||||
);
|
||||
|
@ -2014,7 +1987,7 @@ public abstract class AbstractEntityPersister
|
|||
public Object getCurrentVersion(Object id, SharedSessionContractImplementor session) throws HibernateException {
|
||||
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
LOG.tracev( "Getting version: {0}", MessageHelper.infoString( this, id, getFactory() ) );
|
||||
LOG.tracev( "Getting version: {0}", infoString( this, id, getFactory() ) );
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -2046,7 +2019,7 @@ public abstract class AbstractEntityPersister
|
|||
catch (SQLException e) {
|
||||
throw session.getJdbcServices().getSqlExceptionHelper().convert(
|
||||
e,
|
||||
"could not retrieve version: " + MessageHelper.infoString( this, id, getFactory() ),
|
||||
"could not retrieve version: " + infoString( this, id, getFactory() ),
|
||||
getVersionSelectString()
|
||||
);
|
||||
}
|
||||
|
@ -2238,11 +2211,11 @@ public abstract class AbstractEntityPersister
|
|||
if ( tableNumber == 0 ) {
|
||||
return rootAlias;
|
||||
}
|
||||
StringBuilder buf = new StringBuilder().append( rootAlias );
|
||||
StringBuilder alias = new StringBuilder().append( rootAlias );
|
||||
if ( !rootAlias.endsWith( "_" ) ) {
|
||||
buf.append( '_' );
|
||||
alias.append( '_' );
|
||||
}
|
||||
return buf.append( tableNumber ).append( '_' ).toString();
|
||||
return alias.append( tableNumber ).append( '_' ).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2382,7 +2355,7 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
}
|
||||
|
||||
return ArrayHelper.toIntArray( fields );
|
||||
return toIntArray( fields );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2442,7 +2415,7 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
}
|
||||
|
||||
return ArrayHelper.toIntArray( fields );
|
||||
return toIntArray( fields );
|
||||
}
|
||||
|
||||
private boolean isDirty(
|
||||
|
@ -2718,7 +2691,7 @@ public abstract class AbstractEntityPersister
|
|||
catch (TooManyRowsAffectedException e) {
|
||||
throw new HibernateException(
|
||||
"Duplicate identifier in table for: " +
|
||||
MessageHelper.infoString( this, id, getFactory() )
|
||||
infoString( this, id, getFactory() )
|
||||
);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
|
@ -2954,13 +2927,179 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
}
|
||||
|
||||
protected abstract boolean needsDiscriminator();
|
||||
|
||||
protected boolean isDiscriminatorFormula() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableGroup createRootTableGroup(
|
||||
boolean canUseInnerJoins,
|
||||
NavigablePath navigablePath,
|
||||
String explicitSourceAlias,
|
||||
Supplier<Consumer<Predicate>> additionalPredicateCollectorAccess,
|
||||
SqlAliasBase sqlAliasBase,
|
||||
SqlExpressionResolver expressionResolver,
|
||||
FromClauseAccess fromClauseAccess,
|
||||
SqlAstCreationContext creationContext) {
|
||||
|
||||
final TableReference rootTableReference = new NamedTableReference(
|
||||
needsDiscriminator() ? getRootTableName() : getTableName(),
|
||||
sqlAliasBase.generateNewAlias()
|
||||
);
|
||||
|
||||
final TableGroup tableGroup = new StandardTableGroup(
|
||||
canUseInnerJoins,
|
||||
navigablePath,
|
||||
this,
|
||||
explicitSourceAlias,
|
||||
rootTableReference,
|
||||
true,
|
||||
sqlAliasBase,
|
||||
(tableExpression) -> contains( getSubclassTableNames(), tableExpression ),
|
||||
(tableExpression, tg) -> {
|
||||
final String[] subclassTableNames = getSubclassTableNames();
|
||||
for ( int i = 0; i < subclassTableNames.length; i++ ) {
|
||||
if ( tableExpression.equals( subclassTableNames[ i ] ) ) {
|
||||
final NamedTableReference joinedTableReference = new NamedTableReference(
|
||||
tableExpression,
|
||||
sqlAliasBase.generateNewAlias(),
|
||||
isNullableSubclassTable( i )
|
||||
);
|
||||
return new TableReferenceJoin(
|
||||
shouldInnerJoinSubclassTable( i, emptySet() ),
|
||||
joinedTableReference,
|
||||
additionalPredicateCollectorAccess == null
|
||||
? null
|
||||
: generateJoinPredicate(
|
||||
rootTableReference,
|
||||
joinedTableReference,
|
||||
needsDiscriminator()
|
||||
? getRootTableKeyColumnNames()
|
||||
: getKeyColumnNames(),
|
||||
getSubclassTableKeyColumns( i ),
|
||||
expressionResolver
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
getFactory()
|
||||
);
|
||||
|
||||
if ( additionalPredicateCollectorAccess != null && needsDiscriminator() ) {
|
||||
final String alias = tableGroup.getPrimaryTableReference().getIdentificationVariable();
|
||||
final Predicate discriminatorPredicate = createDiscriminatorPredicate( alias, tableGroup, expressionResolver );
|
||||
additionalPredicateCollectorAccess.get().accept( discriminatorPredicate );
|
||||
}
|
||||
|
||||
return tableGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyDiscriminator(
|
||||
Consumer<Predicate> predicateConsumer,
|
||||
String alias,
|
||||
TableGroup tableGroup,
|
||||
SqlAstCreationState creationState) {
|
||||
// by default, nothing to do
|
||||
if ( needsDiscriminator() ) {
|
||||
predicateConsumer.accept(
|
||||
createDiscriminatorPredicate(
|
||||
alias,
|
||||
tableGroup,
|
||||
creationState.getSqlExpressionResolver()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private Predicate createDiscriminatorPredicate(
|
||||
String alias,
|
||||
TableGroup tableGroup,
|
||||
SqlExpressionResolver sqlExpressionResolver) {
|
||||
final SqlExpressionResolver.ColumnReferenceKey columnReferenceKey;
|
||||
final String discriminatorExpression;
|
||||
if ( isDiscriminatorFormula() ) {
|
||||
discriminatorExpression = getDiscriminatorFormulaTemplate();
|
||||
columnReferenceKey = createColumnReferenceKey(
|
||||
tableGroup.getPrimaryTableReference(),
|
||||
getDiscriminatorFormulaTemplate()
|
||||
);
|
||||
}
|
||||
else {
|
||||
discriminatorExpression = getDiscriminatorColumnName();
|
||||
columnReferenceKey = createColumnReferenceKey(
|
||||
tableGroup.getPrimaryTableReference(),
|
||||
getDiscriminatorColumnName()
|
||||
);
|
||||
}
|
||||
|
||||
final BasicType<?> discriminatorType = (BasicType<?>) getDiscriminatorMapping().getJdbcMapping();
|
||||
final Expression sqlExpression = sqlExpressionResolver.resolveSqlExpression(
|
||||
columnReferenceKey,
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
alias,
|
||||
discriminatorExpression,
|
||||
isDiscriminatorFormula(),
|
||||
null,
|
||||
null,
|
||||
discriminatorType.getJdbcMapping()
|
||||
)
|
||||
);
|
||||
|
||||
return createDisciminatorPredicate( discriminatorType, sqlExpression );
|
||||
}
|
||||
|
||||
private Predicate createDisciminatorPredicate(BasicType<?> discriminatorType, Expression sqlExpression) {
|
||||
if ( hasSubclasses() ) {
|
||||
return createInListPredicate( discriminatorType, sqlExpression );
|
||||
}
|
||||
else {
|
||||
final Object value = getDiscriminatorValue();
|
||||
if ( value == NULL_DISCRIMINATOR ) {
|
||||
return new NullnessPredicate( sqlExpression );
|
||||
}
|
||||
else if ( value == NOT_NULL_DISCRIMINATOR ) {
|
||||
return new NegatedPredicate( new NullnessPredicate( sqlExpression ) );
|
||||
}
|
||||
else {
|
||||
final QueryLiteral<Object> literal = new QueryLiteral<>( value, discriminatorType );
|
||||
return new ComparisonPredicate( sqlExpression, ComparisonOperator.EQUAL, literal );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Predicate createInListPredicate(BasicType<?> discriminatorType, Expression sqlExpression) {
|
||||
final List<Expression> values = new ArrayList<>( fullDiscriminatorValues.length );
|
||||
boolean hasNull = false, hasNonNull = false;
|
||||
for ( Object discriminatorValue : fullDiscriminatorValues ) {
|
||||
if ( discriminatorValue == NULL_DISCRIMINATOR ) {
|
||||
hasNull = true;
|
||||
}
|
||||
else if ( discriminatorValue == NOT_NULL_DISCRIMINATOR ) {
|
||||
hasNonNull = true;
|
||||
}
|
||||
else {
|
||||
values.add( new QueryLiteral<>( discriminatorValue, discriminatorType) );
|
||||
}
|
||||
}
|
||||
final Predicate predicate = new InListPredicate( sqlExpression, values );
|
||||
if ( hasNull || hasNonNull ) {
|
||||
final Junction junction = new Junction( Junction.Nature.DISJUNCTION );
|
||||
|
||||
if ( hasNull && hasNonNull ) {
|
||||
// This means we need to select everything, we don't need a predicate at all
|
||||
// Return an empty Junction
|
||||
return junction;
|
||||
}
|
||||
|
||||
junction.add( new NullnessPredicate( sqlExpression ) );
|
||||
junction.add( predicate );
|
||||
return junction;
|
||||
}
|
||||
return predicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2970,40 +3109,48 @@ public abstract class AbstractEntityPersister
|
|||
boolean useQualifier,
|
||||
Map<String, Filter> enabledFilters,
|
||||
SqlAstCreationState creationState) {
|
||||
if ( filterHelper == null ) {
|
||||
return;
|
||||
if ( filterHelper != null ) {
|
||||
final FilterAliasGenerator filterAliasGenerator = useQualifier && tableGroup != null
|
||||
? getFilterAliasGenerator( tableGroup )
|
||||
: null;
|
||||
filterHelper.applyEnabledFilters( predicateConsumer, filterAliasGenerator, enabledFilters );
|
||||
}
|
||||
|
||||
final FilterAliasGenerator filterAliasGenerator = useQualifier && tableGroup != null
|
||||
? getFilterAliasGenerator( tableGroup )
|
||||
: null;
|
||||
|
||||
filterHelper.applyEnabledFilters( predicateConsumer, filterAliasGenerator, enabledFilters );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyBaseRestrictions(Consumer<Predicate> predicateConsumer, TableGroup tableGroup, boolean useQualifier, Map<String, Filter> enabledFilters, Set<String> treatAsDeclarations, SqlAstCreationState creationState) {
|
||||
public void applyBaseRestrictions(
|
||||
Consumer<Predicate> predicateConsumer,
|
||||
TableGroup tableGroup, boolean useQualifier,
|
||||
Map<String, Filter> enabledFilters,
|
||||
Set<String> treatAsDeclarations,
|
||||
SqlAstCreationState creationState) {
|
||||
applyFilterRestrictions( predicateConsumer, tableGroup, useQualifier, enabledFilters, creationState );
|
||||
applyWhereRestrictions( predicateConsumer, tableGroup, useQualifier, creationState );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyWhereRestrictions(Consumer<Predicate> predicateConsumer, TableGroup tableGroup, boolean useQualifier, SqlAstCreationState creationState) {
|
||||
public void applyWhereRestrictions(
|
||||
Consumer<Predicate> predicateConsumer,
|
||||
TableGroup tableGroup,
|
||||
boolean useQualifier,
|
||||
SqlAstCreationState creationState) {
|
||||
if ( sqlWhereStringTemplate == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String alias;
|
||||
final TableReference tableReference;
|
||||
if ( tableGroup == null || ( tableReference = tableGroup.resolveTableReference( sqlWhereStringTableExpression ) ) == null ) {
|
||||
if ( tableGroup == null ) {
|
||||
alias = null;
|
||||
}
|
||||
else {
|
||||
if ( useQualifier && tableReference.getIdentificationVariable() != null ) {
|
||||
alias = tableReference.getIdentificationVariable();
|
||||
final TableReference tableReference = tableGroup.resolveTableReference( sqlWhereStringTableExpression );
|
||||
if ( tableReference == null ) {
|
||||
alias = null;
|
||||
}
|
||||
else {
|
||||
alias = tableReference.getTableId();
|
||||
alias = useQualifier && tableReference.getIdentificationVariable() != null
|
||||
? tableReference.getIdentificationVariable()
|
||||
: tableReference.getTableId();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3016,14 +3163,12 @@ public abstract class AbstractEntityPersister
|
|||
return rootAlias;
|
||||
}
|
||||
|
||||
protected boolean shouldInnerJoinSubclassTable(
|
||||
int subclassTableNumber,
|
||||
Set<String> treatAsDeclarations) {
|
||||
protected boolean shouldInnerJoinSubclassTable(int subclassTableNumber, Set<String> treatAsDeclarations) {
|
||||
if ( isClassOrSuperclassJoin( subclassTableNumber ) ) {
|
||||
// the table is either this persister's driving table or (one of) its super class persister's driving
|
||||
// tables which can be inner joined as long as the `shouldInnerJoin` condition resolves to true
|
||||
return !isInverseTable( subclassTableNumber )
|
||||
&& !isNullableTable( subclassTableNumber );
|
||||
&& !isNullableTable( subclassTableNumber );
|
||||
}
|
||||
|
||||
// otherwise we have a subclass table and need to look a little deeper...
|
||||
|
@ -3035,9 +3180,7 @@ public abstract class AbstractEntityPersister
|
|||
return isSubclassTableIndicatedByTreatAsDeclarations(subclassTableNumber, treatAsDeclarations);
|
||||
}
|
||||
|
||||
protected boolean isSubclassTableIndicatedByTreatAsDeclarations(
|
||||
int subclassTableNumber,
|
||||
Set<String> treatAsDeclarations) {
|
||||
protected boolean isSubclassTableIndicatedByTreatAsDeclarations(int subclassTableNumber, Set<String> treatAsDeclarations) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3156,7 +3299,7 @@ public abstract class AbstractEntityPersister
|
|||
isOptional,
|
||||
isInverse,
|
||||
isIdentifierTable,
|
||||
ArrayHelper.toIntArray( attributeIndexes ),
|
||||
toIntArray( attributeIndexes ),
|
||||
insertExpectation,
|
||||
customInsertSql,
|
||||
insertCallable,
|
||||
|
@ -3346,7 +3489,7 @@ public abstract class AbstractEntityPersister
|
|||
private Object doLoad(Object id, Object optionalObject, LockOptions lockOptions, Boolean readOnly, SharedSessionContractImplementor session)
|
||||
throws HibernateException {
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
LOG.tracev( "Fetching entity: {0}", MessageHelper.infoString( this, id, getFactory() ) );
|
||||
LOG.tracev( "Fetching entity: {0}", infoString( this, id, getFactory() ) );
|
||||
}
|
||||
|
||||
if ( optionalObject == null ) {
|
||||
|
@ -4129,7 +4272,8 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
}
|
||||
else if ( identifierMapping instanceof NonAggregatedIdentifierMapping ) {
|
||||
final EmbeddedAttributeMapping embeddedAttributeMapping = (EmbeddedAttributeMapping) findAttributeMapping( NavigableRole.IDENTIFIER_MAPPER_PROPERTY );
|
||||
final EmbeddedAttributeMapping embeddedAttributeMapping =
|
||||
(EmbeddedAttributeMapping) findAttributeMapping( NavigableRole.IDENTIFIER_MAPPER_PROPERTY );
|
||||
final AttributeMapping mapping = embeddedAttributeMapping == null
|
||||
? null
|
||||
: embeddedAttributeMapping.getMappedType().findAttributeMapping( basePropertyName );
|
||||
|
@ -4233,18 +4377,13 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
|
||||
// reset the identifier
|
||||
setIdentifier(
|
||||
entity,
|
||||
identifierMapping.getUnsavedStrategy().getDefaultValue( currentId ),
|
||||
session
|
||||
);
|
||||
final Object idDefault = identifierMapping.getUnsavedStrategy().getDefaultValue(currentId);
|
||||
setIdentifier( entity, idDefault, session );
|
||||
|
||||
// reset the version
|
||||
if ( versionMapping != null ) {
|
||||
versionMapping.getVersionAttribute().getPropertyAccess().getSetter().set(
|
||||
entity,
|
||||
versionMapping.getUnsavedStrategy().getDefaultValue( currentVersion )
|
||||
);
|
||||
final Object versionDefault = versionMapping.getUnsavedStrategy().getDefaultValue(currentVersion);
|
||||
versionMapping.getVersionAttribute().getPropertyAccess().getSetter().set( entity, versionDefault );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4296,12 +4435,9 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
|
||||
final Object[] result = new Object[this.attributeMappings.size()];
|
||||
for ( int i = 0; i < this.attributeMappings.size(); i++ ) {
|
||||
result[i] = this.attributeMappings.get( i ).getPropertyAccess().getGetter().getForInsert(
|
||||
entity,
|
||||
mergeMap,
|
||||
session
|
||||
);
|
||||
for ( int i = 0; i < attributeMappings.size(); i++ ) {
|
||||
result[i] = attributeMappings.get( i )
|
||||
.getPropertyAccess().getGetter().getForInsert( entity, mergeMap, session );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -4325,12 +4461,7 @@ public abstract class AbstractEntityPersister
|
|||
throw new UnsupportedOperationException( "Entity has no insert-generated properties - `" + getEntityName() + "`" );
|
||||
}
|
||||
|
||||
insertGeneratedValuesProcessor.processGeneratedValues(
|
||||
entity,
|
||||
id,
|
||||
state,
|
||||
session
|
||||
);
|
||||
insertGeneratedValuesProcessor.processGeneratedValues( entity, id, state, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -4342,12 +4473,7 @@ public abstract class AbstractEntityPersister
|
|||
if ( updateGeneratedValuesProcessor == null ) {
|
||||
throw new AssertionFailure( "Entity has no update-generated properties - `" + getEntityName() + "`" );
|
||||
}
|
||||
updateGeneratedValuesProcessor.processGeneratedValues(
|
||||
entity,
|
||||
id,
|
||||
state,
|
||||
session
|
||||
);
|
||||
updateGeneratedValuesProcessor.processGeneratedValues( entity, id, state, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -4425,7 +4551,7 @@ public abstract class AbstractEntityPersister
|
|||
LOG.tracef(
|
||||
"Resolving natural-id [%s] to id : %s ",
|
||||
Arrays.asList( naturalIdValues ),
|
||||
MessageHelper.infoString( this )
|
||||
infoString( this )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -5631,10 +5757,8 @@ public abstract class AbstractEntityPersister
|
|||
|
||||
private ModelPart getIdentifierModelPart(String name, EntityMappingType treatTargetType) {
|
||||
if ( identifierMapping instanceof NonAggregatedIdentifierMapping ) {
|
||||
final ModelPart subPart = ( (NonAggregatedIdentifierMapping) identifierMapping ).findSubPart(
|
||||
name,
|
||||
treatTargetType
|
||||
);
|
||||
NonAggregatedIdentifierMapping mapping = (NonAggregatedIdentifierMapping) identifierMapping;
|
||||
final ModelPart subPart = mapping.findSubPart( name, treatTargetType );
|
||||
if ( subPart != null ) {
|
||||
return subPart;
|
||||
}
|
||||
|
@ -5648,15 +5772,9 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
|
||||
private boolean isIdentifierReference(String name) {
|
||||
if ( EntityIdentifierMapping.ROLE_LOCAL_NAME.equals( name ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( hasIdentifierProperty() && getIdentifierPropertyName().equals( name ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !entityMetamodel.hasNonIdentifierPropertyNamedId() && "id".equals( name );
|
||||
return EntityIdentifierMapping.ROLE_LOCAL_NAME.equals( name )
|
||||
|| hasIdentifierProperty() && getIdentifierPropertyName().equals( name )
|
||||
|| !entityMetamodel.hasNonIdentifierPropertyNamedId() && "id".equals( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -5664,7 +5782,6 @@ public abstract class AbstractEntityPersister
|
|||
Consumer<ModelPart> consumer,
|
||||
EntityMappingType treatTargetType) {
|
||||
consumer.accept( identifierMapping );
|
||||
|
||||
declaredAttributeMappings.forEachValue( consumer );
|
||||
}
|
||||
|
||||
|
@ -5810,12 +5927,8 @@ public abstract class AbstractEntityPersister
|
|||
int offset,
|
||||
JdbcValuesConsumer valuesConsumer,
|
||||
SharedSessionContractImplementor session) {
|
||||
return getIdentifierMapping().forEachDisassembledJdbcValue(
|
||||
value,
|
||||
offset,
|
||||
valuesConsumer,
|
||||
session
|
||||
);
|
||||
return getIdentifierMapping()
|
||||
.forEachDisassembledJdbcValue( value, offset, valuesConsumer, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -5832,12 +5945,7 @@ public abstract class AbstractEntityPersister
|
|||
else {
|
||||
identifier = identifierMapping.disassemble( identifierMapping.getIdentifier( value ), session );
|
||||
}
|
||||
return identifierMapping.forEachDisassembledJdbcValue(
|
||||
identifier,
|
||||
offset,
|
||||
consumer,
|
||||
session
|
||||
);
|
||||
return identifierMapping.forEachDisassembledJdbcValue( identifier, offset, consumer, session );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -6039,7 +6147,7 @@ public abstract class AbstractEntityPersister
|
|||
boolean isUpdate) throws SQLException, HibernateException {
|
||||
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
LOG.tracev( "Dehydrating entity: {0}", MessageHelper.infoString( this, id, getFactory() ) );
|
||||
LOG.tracev( "Dehydrating entity: {0}", infoString( this, id, getFactory() ) );
|
||||
}
|
||||
|
||||
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
|
||||
|
|
|
@ -31,7 +31,6 @@ 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.jdbc.Expectations;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.Formula;
|
||||
import org.hibernate.mapping.Join;
|
||||
|
@ -44,6 +43,7 @@ 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;
|
||||
|
@ -76,6 +76,10 @@ 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.toStringArray;
|
||||
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;
|
||||
import static org.hibernate.persister.entity.DiscriminatorHelper.NULL_DISCRIMINATOR;
|
||||
|
||||
|
@ -150,6 +154,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
private final BasicType<?> discriminatorType;
|
||||
private final String explicitDiscriminatorColumnName;
|
||||
private final String discriminatorAlias;
|
||||
private final boolean forceDiscriminator;
|
||||
|
||||
// Span of the tables directly mapped by this entity and super-classes, if any
|
||||
private final int coreTableSpan;
|
||||
|
@ -190,10 +195,10 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
// DISCRIMINATOR
|
||||
|
||||
if ( persistentClass.isPolymorphic() ) {
|
||||
forceDiscriminator = persistentClass.isForceDiscriminator();
|
||||
final Value discriminatorMapping = persistentClass.getDiscriminator();
|
||||
if ( discriminatorMapping != null ) {
|
||||
log.debug( "Encountered explicit discriminator mapping for joined inheritance" );
|
||||
|
||||
final Selectable selectable = discriminatorMapping.getSelectables().get(0);
|
||||
if ( selectable instanceof Formula ) {
|
||||
throw new MappingException( "Discriminator formulas on joined inheritance hierarchies not supported at this time" );
|
||||
|
@ -230,6 +235,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
.resolve( StandardBasicTypes.INTEGER );
|
||||
discriminatorValue = null;
|
||||
discriminatorSQLString = null;
|
||||
forceDiscriminator = false;
|
||||
}
|
||||
|
||||
if ( optimisticLockStyle().isAllOrDirty() ) {
|
||||
|
@ -311,10 +317,10 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
}
|
||||
|
||||
hasDuplicateTables = new HashSet<>( tableNames ).size() == tableNames.size();
|
||||
naturalOrderTableNames = ArrayHelper.toStringArray( tableNames );
|
||||
naturalOrderTableKeyColumns = ArrayHelper.to2DStringArray( keyColumns );
|
||||
String[][] naturalOrderTableKeyColumnReaders = ArrayHelper.to2DStringArray(keyColumnReaders);
|
||||
String[][] naturalOrderTableKeyColumnReaderTemplates = ArrayHelper.to2DStringArray(keyColumnReaderTemplates);
|
||||
naturalOrderTableNames = toStringArray( tableNames );
|
||||
naturalOrderTableKeyColumns = to2DStringArray( keyColumns );
|
||||
String[][] naturalOrderTableKeyColumnReaders = to2DStringArray(keyColumnReaders);
|
||||
String[][] naturalOrderTableKeyColumnReaderTemplates = to2DStringArray(keyColumnReaderTemplates);
|
||||
naturalOrderCascadeDeleteEnabled = ArrayHelper.toBooleanArray( cascadeDeletes );
|
||||
|
||||
ArrayList<String> subclassTableNames = new ArrayList<>();
|
||||
|
@ -361,8 +367,8 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
keyColumns.add( key );
|
||||
}
|
||||
|
||||
String[] naturalOrderSubclassTableNameClosure = ArrayHelper.toStringArray( subclassTableNames );
|
||||
String[][] naturalOrderSubclassTableKeyColumnClosure = ArrayHelper.to2DStringArray( keyColumns );
|
||||
String[] naturalOrderSubclassTableNameClosure = toStringArray( subclassTableNames );
|
||||
String[][] naturalOrderSubclassTableKeyColumnClosure = to2DStringArray( keyColumns );
|
||||
isClassOrSuperclassTable = ArrayHelper.toBooleanArray( isConcretes );
|
||||
// subclassTableSequentialSelect = ArrayHelper.toBooleanArray( isDeferreds );
|
||||
// subclassTableIsLazyClosure = ArrayHelper.toBooleanArray( isLazies );
|
||||
|
@ -396,7 +402,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
spaces = ArrayHelper.join(
|
||||
this.tableNames,
|
||||
ArrayHelper.toStringArray( persistentClass.getSynchronizedTables() )
|
||||
toStringArray( persistentClass.getSynchronizedTables() )
|
||||
);
|
||||
|
||||
// Custom sql
|
||||
|
@ -419,7 +425,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
customSQLInsert[jk] = pc.getCustomSQLInsert();
|
||||
insertCallable[jk] = customSQLInsert[jk] != null && pc.isCustomInsertCallable();
|
||||
insertExpectations[jk] = Expectations.appropriateExpectation(
|
||||
insertExpectations[jk] = appropriateExpectation(
|
||||
pc.getCustomSQLInsertCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLInsert[jk], insertCallable[jk] )
|
||||
: pc.getCustomSQLInsertCheckStyle()
|
||||
|
@ -427,7 +433,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
customSQLUpdate[jk] = pc.getCustomSQLUpdate();
|
||||
updateCallable[jk] = customSQLUpdate[jk] != null && pc.isCustomUpdateCallable();
|
||||
updateExpectations[jk] = Expectations.appropriateExpectation(
|
||||
updateExpectations[jk] = appropriateExpectation(
|
||||
pc.getCustomSQLUpdateCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLUpdate[jk], updateCallable[jk] )
|
||||
: pc.getCustomSQLUpdateCheckStyle()
|
||||
|
@ -435,7 +441,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
customSQLDelete[jk] = pc.getCustomSQLDelete();
|
||||
deleteCallable[jk] = customSQLDelete[jk] != null && pc.isCustomDeleteCallable();
|
||||
deleteExpectations[jk] = Expectations.appropriateExpectation(
|
||||
deleteExpectations[jk] = appropriateExpectation(
|
||||
pc.getCustomSQLDeleteCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLDelete[jk], deleteCallable[jk] )
|
||||
: pc.getCustomSQLDeleteCheckStyle()
|
||||
|
@ -456,7 +462,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
customSQLInsert[j] = join.getCustomSQLInsert();
|
||||
insertCallable[j] = customSQLInsert[j] != null && join.isCustomInsertCallable();
|
||||
insertExpectations[j] = Expectations.appropriateExpectation(
|
||||
insertExpectations[j] = appropriateExpectation(
|
||||
join.getCustomSQLInsertCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLInsert[j], insertCallable[j] )
|
||||
: join.getCustomSQLInsertCheckStyle()
|
||||
|
@ -464,7 +470,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
customSQLUpdate[j] = join.getCustomSQLUpdate();
|
||||
updateCallable[j] = customSQLUpdate[j] != null && join.isCustomUpdateCallable();
|
||||
updateExpectations[j] = Expectations.appropriateExpectation(
|
||||
updateExpectations[j] = appropriateExpectation(
|
||||
join.getCustomSQLUpdateCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLUpdate[j], updateCallable[j] )
|
||||
: join.getCustomSQLUpdateCheckStyle()
|
||||
|
@ -472,7 +478,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
customSQLDelete[j] = join.getCustomSQLDelete();
|
||||
deleteCallable[j] = customSQLDelete[j] != null && join.isCustomDeleteCallable();
|
||||
deleteExpectations[j] = Expectations.appropriateExpectation(
|
||||
deleteExpectations[j] = appropriateExpectation(
|
||||
join.getCustomSQLDeleteCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLDelete[j], deleteCallable[j] )
|
||||
: join.getCustomSQLDeleteCheckStyle()
|
||||
|
@ -525,7 +531,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
subclassColumnTableNumberClosure = ArrayHelper.toIntArray( columnTableNumbers );
|
||||
subclassPropertyTableNumberClosure = ArrayHelper.toIntArray( propTableNumbers );
|
||||
// subclassFormulaTableNumberClosure = ArrayHelper.toIntArray( formulaTableNumbers );
|
||||
subclassColumnClosure = ArrayHelper.toStringArray( columns );
|
||||
subclassColumnClosure = toStringArray( columns );
|
||||
|
||||
// SUBCLASSES
|
||||
|
||||
|
@ -669,18 +675,14 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
final Set<String> classNames = new HashSet<>();
|
||||
|
||||
for ( Subclass subclass : persistentClass.getDirectSubclasses() ) {
|
||||
final Set<String> subclassSubclassNames = processPersistentClassHierarchy(
|
||||
subclass,
|
||||
false,
|
||||
factory,
|
||||
mapping
|
||||
);
|
||||
final Set<String> subclassSubclassNames =
|
||||
processPersistentClassHierarchy( subclass, false, factory, mapping );
|
||||
classNames.addAll( subclassSubclassNames );
|
||||
}
|
||||
|
||||
classNames.add( persistentClass.getEntityName() );
|
||||
|
||||
if ( ! isBase ) {
|
||||
if ( !isBase ) {
|
||||
MappedSuperclass msc = persistentClass.getSuperMappedSuperclass();
|
||||
while ( msc != null ) {
|
||||
classNames.add( msc.getMappedClass().getName() );
|
||||
|
@ -699,16 +701,13 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
String[][] mapping,
|
||||
SessionFactoryImplementor factory) {
|
||||
|
||||
final String tableName = persistentClass.getTable().getQualifiedName(
|
||||
factory.getSqlStringGenerationContext()
|
||||
);
|
||||
|
||||
final String tableName = persistentClass.getTable()
|
||||
.getQualifiedName( factory.getSqlStringGenerationContext() );
|
||||
associateSubclassNamesToSubclassTableIndex( tableName, classNames, mapping );
|
||||
|
||||
for ( Join join : persistentClass.getJoins() ) {
|
||||
final String secondaryTableName = join.getTable().getQualifiedName(
|
||||
factory.getSqlStringGenerationContext()
|
||||
);
|
||||
final String secondaryTableName = join.getTable()
|
||||
.getQualifiedName( factory.getSqlStringGenerationContext() );
|
||||
associateSubclassNamesToSubclassTableIndex( secondaryTableName, classNames, mapping );
|
||||
}
|
||||
}
|
||||
|
@ -719,7 +718,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
String[][] mapping) {
|
||||
// find the table's entry in the subclassTableNameClosure array
|
||||
boolean found = false;
|
||||
for ( int i = 0; i < subclassTableNameClosure.length; i++ ) {
|
||||
for ( int i = 1; i < subclassTableNameClosure.length; i++ ) {
|
||||
if ( subclassTableNameClosure[i].equals( tableName ) ) {
|
||||
found = true;
|
||||
final int index = i - coreTableSpan;
|
||||
|
@ -733,7 +732,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
)
|
||||
);
|
||||
}
|
||||
mapping[index] = ArrayHelper.toStringArray( classNames );
|
||||
mapping[index] = toStringArray( classNames );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -747,6 +746,10 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
}
|
||||
}
|
||||
|
||||
protected boolean needsDiscriminator() {
|
||||
return forceDiscriminator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullableTable(int j) {
|
||||
return isNullableTable[j];
|
||||
|
@ -757,7 +760,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
for ( int i = 0; i < naturalOrderTableNames.length; i++ ) {
|
||||
final String tableName = naturalOrderTableNames[i];
|
||||
final int tableIndex = i;
|
||||
|
||||
consumer.consume(
|
||||
tableName,
|
||||
tableIndex,
|
||||
|
@ -852,29 +854,29 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
@Override
|
||||
public String getSubclassForDiscriminatorValue(Object value) {
|
||||
if ( value == null ) {
|
||||
return subclassesByDiscriminatorValue.get( DiscriminatorHelper.NULL_DISCRIMINATOR );
|
||||
return subclassesByDiscriminatorValue.get( NULL_DISCRIMINATOR );
|
||||
}
|
||||
else {
|
||||
String result = subclassesByDiscriminatorValue.get( value );
|
||||
if ( result == null ) {
|
||||
result = subclassesByDiscriminatorValue.get( DiscriminatorHelper.NOT_NULL_DISCRIMINATOR );
|
||||
}
|
||||
return result;
|
||||
final String result = subclassesByDiscriminatorValue.get( value );
|
||||
return result == null ? subclassesByDiscriminatorValue.get( NOT_NULL_DISCRIMINATOR ) : result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<Object, EntityDiscriminatorMapping.DiscriminatorValueDetails> buildDiscriminatorValueMappings(PersistentClass bootEntityDescriptor, MappingModelCreationProcess modelCreationProcess) {
|
||||
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, EntityDiscriminatorMapping.DiscriminatorValueDetails> valueMappings = new ConcurrentHashMap<>();
|
||||
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
|
||||
|
@ -1008,7 +1010,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
@Override
|
||||
public String getRootTableName() {
|
||||
return naturalOrderTableNames[0];
|
||||
return naturalOrderTableNames[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1200,7 +1202,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
final boolean encapsulated = ! cidType.isEmbedded();
|
||||
if ( encapsulated ) {
|
||||
// we have an `@EmbeddedId`
|
||||
return MappingModelCreationHelper.buildEncapsulatedCompositeIdentifierMapping(
|
||||
return buildEncapsulatedCompositeIdentifierMapping(
|
||||
this,
|
||||
bootEntityDescriptor.getIdentifierProperty(),
|
||||
bootEntityDescriptor.getIdentifierProperty().getName(),
|
||||
|
@ -1259,7 +1261,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
protected EntityDiscriminatorMapping generateDiscriminatorMapping(
|
||||
PersistentClass bootEntityDescriptor,
|
||||
MappingModelCreationProcess modelCreationProcess) {
|
||||
EntityMappingType superMappingType = getSuperMappingType();
|
||||
final EntityMappingType superMappingType = getSuperMappingType();
|
||||
if ( superMappingType != null ) {
|
||||
return superMappingType.getDiscriminatorMapping();
|
||||
}
|
||||
|
@ -1273,8 +1275,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
return super.generateDiscriminatorMapping( bootEntityDescriptor, modelCreationProcess );
|
||||
}
|
||||
|
||||
org.hibernate.persister.entity.DiscriminatorType<?> discriminatorMetadataType = (org.hibernate.persister.entity.DiscriminatorType<?>) getTypeDiscriminatorMetadata().getResolutionType();
|
||||
|
||||
// otherwise, we need to use the case-statement approach
|
||||
return new CaseStatementDiscriminatorMappingImpl(
|
||||
this,
|
||||
|
@ -1283,7 +1283,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
notNullColumnNames,
|
||||
discriminatorValues,
|
||||
subclassNameByTableName,
|
||||
discriminatorMetadataType,
|
||||
(DiscriminatorType<?>) getTypeDiscriminatorMetadata().getResolutionType(),
|
||||
buildDiscriminatorValueMappings( bootEntityDescriptor, modelCreationProcess ),
|
||||
modelCreationProcess
|
||||
);
|
||||
|
@ -1394,11 +1394,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
if ( oldJoin.getJoinType() != SqlAstJoinType.INNER
|
||||
&& sharedSuperclassTables.contains( joinedTableReference.getTableExpression() ) ) {
|
||||
tableReferenceJoins.add(
|
||||
new TableReferenceJoin(
|
||||
true,
|
||||
joinedTableReference,
|
||||
oldJoin.getPredicate()
|
||||
)
|
||||
new TableReferenceJoin( true, joinedTableReference, oldJoin.getPredicate() )
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
@ -1418,7 +1414,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
for ( int i = 0; i < constraintOrderedTableNames.length; i++ ) {
|
||||
final String tableName = constraintOrderedTableNames[i];
|
||||
final int tablePosition = i;
|
||||
|
||||
consumer.consume(
|
||||
tableName,
|
||||
() -> columnConsumer -> columnConsumer.accept( tableName, constraintOrderedKeyColumnNames[tablePosition] )
|
||||
|
|
|
@ -13,8 +13,6 @@ 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;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
|
@ -26,11 +24,8 @@ import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
|||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.DynamicFilterAliasGenerator;
|
||||
import org.hibernate.internal.FilterAliasGenerator;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
import org.hibernate.jdbc.Expectations;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.Formula;
|
||||
import org.hibernate.mapping.Join;
|
||||
|
@ -47,32 +42,22 @@ 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;
|
||||
import org.hibernate.query.sqm.ComparisonOperator;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.sql.InFragment;
|
||||
import org.hibernate.sql.ast.spi.FromClauseAccess;
|
||||
import org.hibernate.sql.ast.spi.SqlAliasBase;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
|
||||
import org.hibernate.sql.ast.tree.from.NamedTableReference;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.InListPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.Junction;
|
||||
import org.hibernate.sql.ast.tree.predicate.NegatedPredicate;
|
||||
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.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;
|
||||
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.toSmallMap;
|
||||
import static org.hibernate.jdbc.Expectations.appropriateExpectation;
|
||||
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;
|
||||
|
@ -144,9 +129,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
//private final Map propertyTableNumbersByName = new HashMap();
|
||||
// private final Map<String, Integer> propertyTableNumbersByNameAndSubclass;
|
||||
|
||||
private final String[] fullDiscriminatorSQLValues;
|
||||
private final Object[] fullDiscriminatorValues;
|
||||
|
||||
//INITIALIZATION:
|
||||
|
||||
@Deprecated(since = "6.0")
|
||||
|
@ -202,7 +184,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
customSQLInsert[0] = persistentClass.getCustomSQLInsert();
|
||||
insertCallable[0] = customSQLInsert[0] != null && persistentClass.isCustomInsertCallable();
|
||||
insertExpectations[0] = Expectations.appropriateExpectation(
|
||||
insertExpectations[0] = appropriateExpectation(
|
||||
persistentClass.getCustomSQLInsertCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLInsert[0], insertCallable[0] )
|
||||
: persistentClass.getCustomSQLInsertCheckStyle()
|
||||
|
@ -210,7 +192,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
customSQLUpdate[0] = persistentClass.getCustomSQLUpdate();
|
||||
updateCallable[0] = customSQLUpdate[0] != null && persistentClass.isCustomUpdateCallable();
|
||||
updateExpectations[0] = Expectations.appropriateExpectation(
|
||||
updateExpectations[0] = appropriateExpectation(
|
||||
persistentClass.getCustomSQLUpdateCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLUpdate[0], updateCallable[0] )
|
||||
: persistentClass.getCustomSQLUpdateCheckStyle()
|
||||
|
@ -218,7 +200,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
customSQLDelete[0] = persistentClass.getCustomSQLDelete();
|
||||
deleteCallable[0] = customSQLDelete[0] != null && persistentClass.isCustomDeleteCallable();
|
||||
deleteExpectations[0] = Expectations.appropriateExpectation(
|
||||
deleteExpectations[0] = appropriateExpectation(
|
||||
persistentClass.getCustomSQLDeleteCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLDelete[0], deleteCallable[0] )
|
||||
: persistentClass.getCustomSQLDeleteCheckStyle()
|
||||
|
@ -239,7 +221,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
customSQLInsert[j] = join.getCustomSQLInsert();
|
||||
insertCallable[j] = customSQLInsert[j] != null && join.isCustomInsertCallable();
|
||||
insertExpectations[j] = Expectations.appropriateExpectation(
|
||||
insertExpectations[j] = appropriateExpectation(
|
||||
join.getCustomSQLInsertCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLInsert[j], insertCallable[j] )
|
||||
: join.getCustomSQLInsertCheckStyle()
|
||||
|
@ -247,7 +229,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
customSQLUpdate[j] = join.getCustomSQLUpdate();
|
||||
updateCallable[j] = customSQLUpdate[j] != null && join.isCustomUpdateCallable();
|
||||
updateExpectations[j] = Expectations.appropriateExpectation(
|
||||
updateExpectations[j] = appropriateExpectation(
|
||||
join.getCustomSQLUpdateCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLUpdate[j], updateCallable[j] )
|
||||
: join.getCustomSQLUpdateCheckStyle()
|
||||
|
@ -255,7 +237,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
customSQLDelete[j] = join.getCustomSQLDelete();
|
||||
deleteCallable[j] = customSQLDelete[j] != null && join.isCustomDeleteCallable();
|
||||
deleteExpectations[j] = Expectations.appropriateExpectation(
|
||||
deleteExpectations[j] = appropriateExpectation(
|
||||
join.getCustomSQLDeleteCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLDelete[j], deleteCallable[j] )
|
||||
: join.getCustomSQLDeleteCheckStyle()
|
||||
|
@ -279,7 +261,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
spaces = ArrayHelper.join(
|
||||
qualifiedTableNames,
|
||||
ArrayHelper.toStringArray( persistentClass.getSynchronizedTables() )
|
||||
toStringArray( persistentClass.getSynchronizedTables() )
|
||||
);
|
||||
|
||||
// final boolean lazyAvailable = isInstrumented();
|
||||
|
@ -294,12 +276,12 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
// ArrayList<Boolean> isLazies = new ArrayList<>();
|
||||
subclassTables.add( qualifiedTableNames[0] );
|
||||
joinKeyColumns.add( getIdentifierColumnNames() );
|
||||
isConcretes.add( Boolean.TRUE );
|
||||
isClassOrSuperclassJoins.add( Boolean.TRUE );
|
||||
// isDeferreds.add( Boolean.FALSE );
|
||||
isInverses.add( Boolean.FALSE );
|
||||
isNullables.add( Boolean.FALSE );
|
||||
// isLazies.add( Boolean.FALSE );
|
||||
isConcretes.add( true );
|
||||
isClassOrSuperclassJoins.add( true );
|
||||
// isDeferreds.add( false );
|
||||
isInverses.add( false );
|
||||
isNullables.add( false );
|
||||
// isLazies.add( false );
|
||||
for ( Join join : persistentClass.getSubclassJoinClosure() ) {
|
||||
isConcretes.add( persistentClass.isClassOrSuperclassTable( join.getTable() ) );
|
||||
isClassOrSuperclassJoins.add( persistentClass.isClassOrSuperclassJoin( join ) );
|
||||
|
@ -310,26 +292,25 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
// boolean isDeferred = join.isSequentialSelect() && !persistentClass.isClassOrSuperclassJoin( join );
|
||||
// isDeferreds.add( isDeferred );
|
||||
|
||||
String joinTableName = determineTableName( join.getTable() );
|
||||
final String joinTableName = determineTableName( join.getTable() );
|
||||
subclassTables.add( joinTableName );
|
||||
|
||||
String[] keyCols = new String[join.getKey().getColumnSpan()];
|
||||
final String[] keyCols = new String[join.getKey().getColumnSpan()];
|
||||
List<Column> columns = join.getKey().getColumns();
|
||||
for ( int i = 0; i < columns.size(); i++ ) {
|
||||
Column col = columns.get( i );
|
||||
keyCols[i] = col.getQuotedName( dialect );
|
||||
keyCols[i] = columns.get( i ).getQuotedName( dialect );
|
||||
}
|
||||
joinKeyColumns.add( keyCols );
|
||||
}
|
||||
|
||||
// subclassTableSequentialSelect = ArrayHelper.toBooleanArray( isDeferreds );
|
||||
subclassTableNameClosure = ArrayHelper.toStringArray( subclassTables );
|
||||
subclassTableNameClosure = toStringArray( subclassTables );
|
||||
// subclassTableIsLazyClosure = ArrayHelper.toBooleanArray( isLazies );
|
||||
subclassTableKeyColumnClosure = ArrayHelper.to2DStringArray( joinKeyColumns );
|
||||
isClassOrSuperclassTable = ArrayHelper.toBooleanArray( isConcretes );
|
||||
isClassOrSuperclassJoin = ArrayHelper.toBooleanArray( isClassOrSuperclassJoins );
|
||||
isInverseSubclassTable = ArrayHelper.toBooleanArray( isInverses );
|
||||
isNullableSubclassTable = ArrayHelper.toBooleanArray( isNullables );
|
||||
subclassTableKeyColumnClosure = to2DStringArray( joinKeyColumns );
|
||||
isClassOrSuperclassTable = toBooleanArray( isConcretes );
|
||||
isClassOrSuperclassJoin = toBooleanArray( isClassOrSuperclassJoins );
|
||||
isInverseSubclassTable = toBooleanArray( isInverses );
|
||||
isNullableSubclassTable = toBooleanArray( isNullables );
|
||||
|
||||
// DISCRIMINATOR
|
||||
|
||||
|
@ -339,7 +320,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
throw new MappingException( "discriminator mapping required for single table polymorphic persistence" );
|
||||
}
|
||||
forceDiscriminator = persistentClass.isForceDiscriminator();
|
||||
Selectable selectable = discriminator.getSelectables().get( 0 );
|
||||
final Selectable selectable = discriminator.getSelectables().get( 0 );
|
||||
SqmFunctionRegistry functionRegistry = factory.getQueryEngine().getSqmFunctionRegistry();
|
||||
discriminatorType = DiscriminatorHelper.getDiscriminatorType( persistentClass );
|
||||
discriminatorValue = DiscriminatorHelper.getDiscriminatorValue( persistentClass );
|
||||
|
@ -359,7 +340,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
discriminatorAlias = "clazz_";
|
||||
}
|
||||
else {
|
||||
Column column = (Column) selectable;
|
||||
final Column column = (Column) selectable;
|
||||
discriminatorColumnName = column.getQuotedName( dialect );
|
||||
discriminatorColumnReaders = column.getReadExpr( dialect );
|
||||
discriminatorColumnReaderTemplate = column.getTemplate(
|
||||
|
@ -389,7 +370,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
// PROPERTIES
|
||||
|
||||
propertyTableNumbers = new int[getPropertySpan()];
|
||||
List<Property> propertyClosure = persistentClass.getPropertyClosure();
|
||||
final List<Property> propertyClosure = persistentClass.getPropertyClosure();
|
||||
for ( int k = 0; k < propertyClosure.size(); k++ ) {
|
||||
propertyTableNumbers[k] = persistentClass.getJoinNumber( propertyClosure.get( k ) );
|
||||
}
|
||||
|
@ -408,10 +389,8 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
propertyJoinNumbers.add( join );
|
||||
}
|
||||
|
||||
subclassPropertyTableNumberClosure = ArrayHelper.toIntArray( propertyJoinNumbers );
|
||||
subclassPropertyTableNumberClosure = toIntArray( propertyJoinNumbers );
|
||||
|
||||
final List<Object> values = new ArrayList<>();
|
||||
final List<String> sqlValues = new ArrayList<>();
|
||||
int subclassSpan = persistentClass.getSubclassSpan() + 1;
|
||||
subclassClosure = new String[subclassSpan];
|
||||
subclassClosure[0] = getEntityName();
|
||||
|
@ -422,13 +401,8 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
getEntityName()
|
||||
);
|
||||
|
||||
if ( !getEntityMetamodel().isAbstract() ) {
|
||||
values.add( discriminatorValue );
|
||||
sqlValues.add( discriminatorSQLValue );
|
||||
}
|
||||
|
||||
// SUBCLASSES
|
||||
List<Subclass> subclasses = persistentClass.getSubclasses();
|
||||
final List<Subclass> subclasses = persistentClass.getSubclasses();
|
||||
for ( int k = 0; k < subclasses.size(); k++ ) {
|
||||
Subclass subclass = subclasses.get( k );
|
||||
subclassClosure[k] = subclass.getEntityName();
|
||||
|
@ -438,23 +412,11 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
subclassDiscriminatorValue,
|
||||
subclass.getEntityName()
|
||||
);
|
||||
|
||||
//copy/paste from EntityMetamodel:
|
||||
boolean subclassAbstract = subclass.isAbstract() == null
|
||||
? subclass.hasPojoRepresentation() && ReflectHelper.isAbstractClass( subclass.getMappedClass() )
|
||||
: subclass.isAbstract();
|
||||
|
||||
if ( !subclassAbstract ) {
|
||||
values.add( subclassDiscriminatorValue );
|
||||
sqlValues.add( DiscriminatorHelper.getDiscriminatorSQLValue( subclass, dialect, factory ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Don't hold a reference to an empty HashMap:
|
||||
subclassesByDiscriminatorValue = CollectionHelper.toSmallMap( subclassesByDiscriminatorValueLocal );
|
||||
fullDiscriminatorSQLValues = ArrayHelper.toStringArray( sqlValues );
|
||||
fullDiscriminatorValues = ArrayHelper.toObjectArray( values );
|
||||
subclassesByDiscriminatorValue = toSmallMap( subclassesByDiscriminatorValueLocal );
|
||||
|
||||
initSubclassPropertyAliasesMap( persistentClass );
|
||||
|
||||
|
@ -463,16 +425,16 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
private static boolean isDiscriminatorInsertable(PersistentClass persistentClass) {
|
||||
return !persistentClass.isDiscriminatorValueNull()
|
||||
&& !persistentClass.isDiscriminatorValueNotNull()
|
||||
&& persistentClass.isDiscriminatorInsertable()
|
||||
&& !persistentClass.getDiscriminator().hasFormula();
|
||||
&& !persistentClass.isDiscriminatorValueNotNull()
|
||||
&& persistentClass.isDiscriminatorInsertable()
|
||||
&& !persistentClass.getDiscriminator().hasFormula();
|
||||
}
|
||||
|
||||
private static void addSubclassByDiscriminatorValue(
|
||||
Map<Object, String> subclassesByDiscriminatorValue,
|
||||
Object discriminatorValue,
|
||||
String entityName) {
|
||||
String mappedEntityName = subclassesByDiscriminatorValue.put( discriminatorValue, entityName );
|
||||
final String mappedEntityName = subclassesByDiscriminatorValue.put( discriminatorValue, entityName );
|
||||
if ( mappedEntityName != null ) {
|
||||
throw new MappingException(
|
||||
"Entities [" + entityName + "] and [" + mappedEntityName
|
||||
|
@ -561,11 +523,8 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
return subclassesByDiscriminatorValue.get( NULL_DISCRIMINATOR );
|
||||
}
|
||||
else {
|
||||
String result = subclassesByDiscriminatorValue.get( value );
|
||||
if ( result == null ) {
|
||||
result = subclassesByDiscriminatorValue.get( DiscriminatorHelper.NOT_NULL_DISCRIMINATOR );
|
||||
}
|
||||
return result;
|
||||
final String result = subclassesByDiscriminatorValue.get( value );
|
||||
return result == null ? subclassesByDiscriminatorValue.get( NOT_NULL_DISCRIMINATOR ) : result;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -574,7 +533,8 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
return spaces;
|
||||
}
|
||||
|
||||
private boolean isDiscriminatorFormula() {
|
||||
@Override
|
||||
protected boolean isDiscriminatorFormula() {
|
||||
return discriminatorColumnName == null;
|
||||
}
|
||||
|
||||
|
@ -615,7 +575,8 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
return getTableName() + ' ' + name;
|
||||
}
|
||||
|
||||
private boolean needsDiscriminator() {
|
||||
@Override
|
||||
protected boolean needsDiscriminator() {
|
||||
return forceDiscriminator || isInherited();
|
||||
}
|
||||
|
||||
|
@ -716,11 +677,12 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
.getMappingMetamodel();
|
||||
|
||||
//noinspection unchecked
|
||||
final JdbcLiteralFormatter<Object> jdbcLiteralFormatter = (JdbcLiteralFormatter<Object>) discriminatorType.getJdbcLiteralFormatter();
|
||||
final Dialect dialect = modelCreationProcess.getCreationContext().getSessionFactory().getJdbcServices().getDialect();
|
||||
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
|
||||
|
@ -751,142 +713,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
return new DynamicFilterAliasGenerator( qualifiedTableNames, rootAlias );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableGroup createRootTableGroup(
|
||||
boolean canUseInnerJoins,
|
||||
NavigablePath navigablePath,
|
||||
String explicitSourceAlias,
|
||||
Supplier<Consumer<Predicate>> additionalPredicateCollectorAccess,
|
||||
SqlAliasBase sqlAliasBase,
|
||||
SqlExpressionResolver expressionResolver,
|
||||
FromClauseAccess fromClauseAccess,
|
||||
SqlAstCreationContext creationContext) {
|
||||
final TableGroup tableGroup = super.createRootTableGroup(
|
||||
canUseInnerJoins,
|
||||
navigablePath,
|
||||
explicitSourceAlias,
|
||||
additionalPredicateCollectorAccess,
|
||||
sqlAliasBase,
|
||||
expressionResolver,
|
||||
fromClauseAccess,
|
||||
creationContext
|
||||
);
|
||||
|
||||
if ( additionalPredicateCollectorAccess != null && needsDiscriminator() ) {
|
||||
final Predicate discriminatorPredicate = createDiscriminatorPredicate(
|
||||
tableGroup.getPrimaryTableReference().getIdentificationVariable(),
|
||||
tableGroup,
|
||||
expressionResolver
|
||||
);
|
||||
additionalPredicateCollectorAccess.get().accept( discriminatorPredicate );
|
||||
}
|
||||
|
||||
return tableGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyDiscriminator(
|
||||
Consumer<Predicate> predicateConsumer,
|
||||
String alias,
|
||||
TableGroup tableGroup,
|
||||
SqlAstCreationState creationState) {
|
||||
if ( needsDiscriminator() ) {
|
||||
predicateConsumer.accept(
|
||||
createDiscriminatorPredicate(
|
||||
alias,
|
||||
tableGroup,
|
||||
creationState.getSqlExpressionResolver()
|
||||
)
|
||||
);
|
||||
}
|
||||
super.applyDiscriminator( predicateConsumer, alias, tableGroup, creationState );
|
||||
}
|
||||
|
||||
private Predicate createDiscriminatorPredicate(
|
||||
String alias,
|
||||
TableGroup tableGroup,
|
||||
SqlExpressionResolver sqlExpressionResolver) {
|
||||
final SqlExpressionResolver.ColumnReferenceKey columnReferenceKey;
|
||||
final String discriminatorExpression;
|
||||
if ( isDiscriminatorFormula() ) {
|
||||
discriminatorExpression = getDiscriminatorFormulaTemplate();
|
||||
columnReferenceKey = SqlExpressionResolver.createColumnReferenceKey(
|
||||
tableGroup.getPrimaryTableReference(),
|
||||
getDiscriminatorFormulaTemplate()
|
||||
);
|
||||
}
|
||||
else {
|
||||
discriminatorExpression = getDiscriminatorColumnName();
|
||||
columnReferenceKey = SqlExpressionResolver.createColumnReferenceKey(
|
||||
tableGroup.getPrimaryTableReference(),
|
||||
getDiscriminatorColumnName()
|
||||
);
|
||||
}
|
||||
|
||||
final BasicType<?> discriminatorType = (BasicType<?>) getDiscriminatorMapping().getJdbcMapping();
|
||||
final Expression sqlExpression = sqlExpressionResolver.resolveSqlExpression(
|
||||
columnReferenceKey,
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
alias,
|
||||
discriminatorExpression,
|
||||
isDiscriminatorFormula(),
|
||||
null,
|
||||
null,
|
||||
discriminatorType.getJdbcMapping()
|
||||
)
|
||||
);
|
||||
|
||||
if ( hasSubclasses() ) {
|
||||
final List<Expression> values = new ArrayList<>( fullDiscriminatorValues.length );
|
||||
boolean hasNull = false, hasNonNull = false;
|
||||
for ( Object discriminatorValue : fullDiscriminatorValues ) {
|
||||
if ( discriminatorValue == NULL_DISCRIMINATOR ) {
|
||||
hasNull = true;
|
||||
}
|
||||
else if ( discriminatorValue == DiscriminatorHelper.NOT_NULL_DISCRIMINATOR ) {
|
||||
hasNonNull = true;
|
||||
}
|
||||
else {
|
||||
values.add( new QueryLiteral<>( discriminatorValue, discriminatorType ) );
|
||||
}
|
||||
}
|
||||
final Predicate p = new InListPredicate( sqlExpression, values );
|
||||
if ( hasNull || hasNonNull ) {
|
||||
final Junction junction = new Junction(
|
||||
Junction.Nature.DISJUNCTION
|
||||
);
|
||||
|
||||
// This essentially means we need to select everything, so we don't need a predicate at all
|
||||
// so we return an empty Junction
|
||||
if ( hasNull && hasNonNull ) {
|
||||
return junction;
|
||||
}
|
||||
|
||||
junction.add( new NullnessPredicate( sqlExpression ) );
|
||||
junction.add( p );
|
||||
return junction;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
final Object value = getDiscriminatorValue();
|
||||
final boolean hasNotNullDiscriminator = value == DiscriminatorHelper.NOT_NULL_DISCRIMINATOR;
|
||||
final boolean hasNullDiscriminator = value == NULL_DISCRIMINATOR;
|
||||
if ( hasNotNullDiscriminator || hasNullDiscriminator ) {
|
||||
final NullnessPredicate nullnessPredicate = new NullnessPredicate( sqlExpression );
|
||||
if ( hasNotNullDiscriminator ) {
|
||||
return new NegatedPredicate( nullnessPredicate );
|
||||
}
|
||||
|
||||
return nullnessPredicate;
|
||||
}
|
||||
return new ComparisonPredicate(
|
||||
sqlExpression,
|
||||
ComparisonOperator.EQUAL,
|
||||
new QueryLiteral<>( value, discriminatorType )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pruneForSubclasses(TableGroup tableGroup, Set<String> treatedEntityNames) {
|
||||
if ( !needsDiscriminator() && treatedEntityNames.isEmpty() ) {
|
||||
|
@ -913,8 +739,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
}
|
||||
if ( treatTargetType.hasSubclasses() ) {
|
||||
// if the treat is an abstract class, add the concrete implementations to values if any
|
||||
Set<String> actualSubClasses = treatTargetType.getSubclassEntityNames();
|
||||
|
||||
final Set<String> actualSubClasses = treatTargetType.getSubclassEntityNames();
|
||||
for ( String actualSubClass : actualSubClasses ) {
|
||||
if ( actualSubClass.equals( subclass ) ) {
|
||||
continue;
|
||||
|
@ -938,7 +763,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
for ( int i = 0; i < constraintOrderedTableNames.length; i++ ) {
|
||||
final String tableName = constraintOrderedTableNames[i];
|
||||
final int tablePosition = i;
|
||||
|
||||
consumer.consume(
|
||||
tableName,
|
||||
() -> columnConsumer -> columnConsumer.accept(
|
||||
|
@ -954,11 +778,10 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
for ( int i = 0; i < qualifiedTableNames.length; i++ ) {
|
||||
final String tableName = qualifiedTableNames[i];
|
||||
final int tableIndex = i;
|
||||
|
||||
consumer.consume(
|
||||
tableName,
|
||||
tableIndex,
|
||||
() -> (columnConsumer) -> columnConsumer.accept(
|
||||
() -> columnConsumer -> columnConsumer.accept(
|
||||
tableName,
|
||||
getIdentifierMapping(),
|
||||
keyColumnNames[tableIndex]
|
||||
|
|
|
@ -258,6 +258,14 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnionTableReference createPrimaryTableReference(
|
||||
SqlAliasBase sqlAliasBase,
|
||||
SqlExpressionResolver expressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
return new UnionTableReference( getTableName(), subclassTableExpressions, sqlAliasBase.generateNewAlias() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableGroup createRootTableGroup(
|
||||
boolean canUseInnerJoins,
|
||||
|
@ -268,19 +276,18 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
|||
SqlExpressionResolver expressionResolver,
|
||||
FromClauseAccess fromClauseAccess,
|
||||
SqlAstCreationContext creationContext) {
|
||||
final UnionTableReference tableReference = resolvePrimaryTableReference( sqlAliasBase );
|
||||
|
||||
return new UnionTableGroup( canUseInnerJoins, navigablePath, tableReference, this, explicitSourceAlias );
|
||||
return new UnionTableGroup(
|
||||
canUseInnerJoins,
|
||||
navigablePath,
|
||||
createPrimaryTableReference( sqlAliasBase, expressionResolver, creationContext ),
|
||||
this,
|
||||
explicitSourceAlias
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UnionTableReference resolvePrimaryTableReference(SqlAliasBase sqlAliasBase) {
|
||||
return new UnionTableReference(
|
||||
getTableName(),
|
||||
subclassTableExpressions,
|
||||
sqlAliasBase.generateNewAlias(),
|
||||
false
|
||||
);
|
||||
protected boolean needsDiscriminator() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -167,7 +167,6 @@ public abstract class AbstractCteMutationHandler extends AbstractMutationHandler
|
|||
.buildSelectTranslator( factory, statement );
|
||||
|
||||
final Expression count = createCountStar( factory, sqmConverter );
|
||||
//noinspection rawtypes,unchecked
|
||||
domainResults.add(
|
||||
new BasicResult<>(
|
||||
0,
|
||||
|
@ -180,8 +179,7 @@ public abstract class AbstractCteMutationHandler extends AbstractMutationHandler
|
|||
new CteTableGroup(
|
||||
new NamedTableReference(
|
||||
idSelectCte.getCteTable().getTableExpression(),
|
||||
CTE_TABLE_IDENTIFIER,
|
||||
false
|
||||
CTE_TABLE_IDENTIFIER
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -270,8 +268,7 @@ public abstract class AbstractCteMutationHandler extends AbstractMutationHandler
|
|||
SessionFactoryImplementor factory) {
|
||||
final NamedTableReference idSelectTableReference = new NamedTableReference(
|
||||
idSelectCte.getCteTable().getTableExpression(),
|
||||
CTE_TABLE_IDENTIFIER,
|
||||
false
|
||||
CTE_TABLE_IDENTIFIER
|
||||
);
|
||||
final List<CteColumn> cteColumns = idSelectCte.getCteTable().getCteColumns();
|
||||
final int size = cteColumns.size();
|
||||
|
|
|
@ -412,13 +412,7 @@ public class CteInsertHandler implements InsertHandler {
|
|||
{
|
||||
final QuerySpec rowsWithSequenceQuery = new QuerySpec( true );
|
||||
rowsWithSequenceQuery.getFromClause().addRoot(
|
||||
new CteTableGroup(
|
||||
new NamedTableReference(
|
||||
baseTableName,
|
||||
"e",
|
||||
false
|
||||
)
|
||||
)
|
||||
new CteTableGroup( new NamedTableReference( baseTableName, "e" ) )
|
||||
);
|
||||
rowsWithSequenceQuery.getSelectClause().addSqlSelection(
|
||||
new SqlSelectionImpl(
|
||||
|
@ -469,18 +463,13 @@ public class CteInsertHandler implements InsertHandler {
|
|||
final TableGroup baseTableGroup = new TableGroupImpl(
|
||||
navigablePath,
|
||||
null,
|
||||
new NamedTableReference(
|
||||
baseTableName,
|
||||
"e",
|
||||
false
|
||||
),
|
||||
new NamedTableReference( baseTableName, "e" ),
|
||||
null
|
||||
);
|
||||
final TableGroup rowsWithSequenceTableGroup = new CteTableGroup(
|
||||
new NamedTableReference(
|
||||
ROW_NUMBERS_WITH_SEQUENCE_VALUE,
|
||||
"t",
|
||||
false
|
||||
"t"
|
||||
)
|
||||
);
|
||||
baseTableGroup.addTableGroupJoin(
|
||||
|
@ -639,8 +628,7 @@ public class CteInsertHandler implements InsertHandler {
|
|||
new NamedTableReference(
|
||||
// We want to return the insertion count of the base table
|
||||
baseInsertCte,
|
||||
CTE_TABLE_IDENTIFIER,
|
||||
false
|
||||
CTE_TABLE_IDENTIFIER
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -815,11 +803,7 @@ public class CteInsertHandler implements InsertHandler {
|
|||
final String baseTableName = "base_" + queryCte.getCteTable().getTableExpression();
|
||||
insertSelectSpec.getFromClause().addRoot(
|
||||
new CteTableGroup(
|
||||
new NamedTableReference(
|
||||
baseTableName,
|
||||
"e",
|
||||
false
|
||||
)
|
||||
new NamedTableReference( baseTableName, "e" )
|
||||
)
|
||||
);
|
||||
final CteColumn rowNumberColumn = queryCte.getCteTable().getCteColumns().get(
|
||||
|
@ -864,18 +848,13 @@ public class CteInsertHandler implements InsertHandler {
|
|||
final TableGroup baseTableGroup = new TableGroupImpl(
|
||||
navigablePath,
|
||||
null,
|
||||
new NamedTableReference(
|
||||
baseTableName,
|
||||
"e",
|
||||
false
|
||||
),
|
||||
new NamedTableReference( baseTableName, "e" ),
|
||||
null
|
||||
);
|
||||
final TableGroup rootInsertCteTableGroup = new CteTableGroup(
|
||||
new NamedTableReference(
|
||||
getCteTableName( tableExpression ),
|
||||
"t",
|
||||
false
|
||||
"t"
|
||||
)
|
||||
);
|
||||
baseTableGroup.addTableGroupJoin(
|
||||
|
@ -947,8 +926,7 @@ public class CteInsertHandler implements InsertHandler {
|
|||
new CteTableGroup(
|
||||
new NamedTableReference(
|
||||
dmlResultCte.getTableExpression(),
|
||||
"e",
|
||||
false
|
||||
"e"
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -997,8 +975,7 @@ public class CteInsertHandler implements InsertHandler {
|
|||
new CteTableGroup(
|
||||
new NamedTableReference(
|
||||
queryCte.getCteTable().getTableExpression(),
|
||||
"e",
|
||||
false
|
||||
"e"
|
||||
)
|
||||
)
|
||||
);
|
||||
|
|
|
@ -181,8 +181,7 @@ public class CteUpdateHandler extends AbstractCteMutationHandler implements Upda
|
|||
);
|
||||
final NamedTableReference existsTableReference = new NamedTableReference(
|
||||
tableExpression,
|
||||
"dml_",
|
||||
false
|
||||
"dml_"
|
||||
);
|
||||
final List<ColumnReference> existsKeyColumns = new ArrayList<>( idSelectCte.getCteTable().getCteColumns().size() );
|
||||
final String[] keyColumns = entityPersister.getKeyColumns( i );
|
||||
|
|
|
@ -157,8 +157,7 @@ public class InlineDeleteHandler implements DeleteHandler {
|
|||
DomainQueryExecutionContext executionContext) {
|
||||
final NamedTableReference targetTableReference = new NamedTableReference(
|
||||
targetTableExpression,
|
||||
DeleteStatement.DEFAULT_ALIAS,
|
||||
false
|
||||
DeleteStatement.DEFAULT_ALIAS
|
||||
);
|
||||
|
||||
final SqmJdbcExecutionContextAdapter executionContextAdapter = SqmJdbcExecutionContextAdapter.omittingLockingAndPaging( executionContext );
|
||||
|
|
|
@ -67,8 +67,7 @@ public final class ExecuteWithTemporaryTableHelper {
|
|||
|
||||
final NamedTableReference idTableReference = new NamedTableReference(
|
||||
idTable.getTableExpression(),
|
||||
InsertSelectStatement.DEFAULT_ALIAS,
|
||||
false
|
||||
InsertSelectStatement.DEFAULT_ALIAS
|
||||
);
|
||||
final InsertSelectStatement idTableInsert = new InsertSelectStatement( idTableReference );
|
||||
|
||||
|
|
|
@ -323,8 +323,7 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
|
|||
final QuerySpec querySpec = new QuerySpec( true );
|
||||
final NamedTableReference temporaryTableReference = new NamedTableReference(
|
||||
insertStatement.getTargetTable().getTableExpression(),
|
||||
updatingTableReference.getIdentificationVariable(),
|
||||
false
|
||||
updatingTableReference.getIdentificationVariable()
|
||||
);
|
||||
final TableGroupImpl temporaryTableGroup = new TableGroupImpl(
|
||||
updatingTableGroup.getNavigablePath(),
|
||||
|
@ -687,8 +686,7 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
|
|||
null,
|
||||
new NamedTableReference(
|
||||
insertStatement.getTargetTable().getTableExpression(),
|
||||
updatingTableReference.getIdentificationVariable(),
|
||||
false
|
||||
updatingTableReference.getIdentificationVariable()
|
||||
),
|
||||
entityDescriptor
|
||||
);
|
||||
|
|
|
@ -297,8 +297,7 @@ public class RestrictedDeleteExecutionDelegate implements TableBasedDeleteHandle
|
|||
(tableExpression, tableKeyColumnVisitationSupplier) -> {
|
||||
final NamedTableReference tableReference = new NamedTableReference(
|
||||
tableExpression,
|
||||
tableGroup.getPrimaryTableReference().getIdentificationVariable(),
|
||||
false
|
||||
tableGroup.getPrimaryTableReference().getIdentificationVariable()
|
||||
);
|
||||
final QuerySpec idMatchingSubQuerySpec;
|
||||
// No need for a predicate if there is no supplied predicate i.e. this is a full cleanup
|
||||
|
|
|
@ -338,8 +338,7 @@ public class UpdateExecutionDelegate implements TableBasedUpdateHandler.Executio
|
|||
);
|
||||
final NamedTableReference existsTableReference = new NamedTableReference(
|
||||
tableExpression,
|
||||
"dml_",
|
||||
false
|
||||
"dml_"
|
||||
);
|
||||
existsQuerySpec.getFromClause().addRoot(
|
||||
new TableGroupImpl(
|
||||
|
|
|
@ -2836,7 +2836,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
navigablePath,
|
||||
sqlAliasBase,
|
||||
tableGroupProducer,
|
||||
new NamedTableReference( cteName, identifierVariable, false ),
|
||||
new NamedTableReference( cteName, identifierVariable ),
|
||||
tableGroupProducer.getCompatibleTableExpressions()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,12 @@ public class NamedTableReference extends AbstractTableReference {
|
|||
|
||||
private String prunedTableExpression;
|
||||
|
||||
public NamedTableReference(
|
||||
String tableExpression,
|
||||
String identificationVariable) {
|
||||
this( tableExpression, identificationVariable, false );
|
||||
}
|
||||
|
||||
public NamedTableReference(
|
||||
String tableExpression,
|
||||
String identificationVariable,
|
||||
|
|
|
@ -19,6 +19,13 @@ import static org.hibernate.internal.util.StringHelper.isEmpty;
|
|||
public class UnionTableReference extends NamedTableReference {
|
||||
private final String[] subclassTableSpaceExpressions;
|
||||
|
||||
public UnionTableReference(
|
||||
String unionTableExpression,
|
||||
String[] subclassTableSpaceExpressions,
|
||||
String identificationVariable) {
|
||||
this( unionTableExpression, subclassTableSpaceExpressions, identificationVariable, false );
|
||||
}
|
||||
|
||||
public UnionTableReference(
|
||||
String unionTableExpression,
|
||||
String[] subclassTableSpaceExpressions,
|
||||
|
|
|
@ -0,0 +1,207 @@
|
|||
package org.hibernate.orm.test.inheritance.repeatedtable;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.annotations.DiscriminatorOptions;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
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.assertTrue;
|
||||
import static org.hibernate.cfg.AvailableSettings.FORMAT_SQL;
|
||||
import static org.hibernate.cfg.AvailableSettings.SHOW_SQL;
|
||||
|
||||
public class RepeatedTableTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class[] getAnnotatedClasses() {
|
||||
return new Class[]{
|
||||
DataType.class,
|
||||
ObjectType.class,
|
||||
SimpleType.class,
|
||||
Prop.class
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(Configuration configuration) {
|
||||
super.configure(configuration);
|
||||
configuration.setProperty(SHOW_SQL, Boolean.toString(true));
|
||||
configuration.setProperty(FORMAT_SQL, Boolean.toString(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_append_properties() {
|
||||
Long id;
|
||||
Long sId;
|
||||
try (Session sess = openSession()) {
|
||||
Transaction tx = sess.beginTransaction();
|
||||
|
||||
SimpleType simpleType = new SimpleType();
|
||||
simpleType.setName("simple");
|
||||
simpleType.setCount(69);
|
||||
sess.persist(simpleType);
|
||||
sId = simpleType.getId();
|
||||
|
||||
ObjectType objectType = new ObjectType();
|
||||
objectType.setName("name");
|
||||
sess.persist(objectType);
|
||||
id = objectType.getId();
|
||||
|
||||
tx.commit();
|
||||
}
|
||||
|
||||
try (Session sess = openSession()) {
|
||||
Transaction tx = sess.beginTransaction();
|
||||
ObjectType objectType = sess.find(ObjectType.class, id);
|
||||
Prop property = new Prop();
|
||||
property.setName("Prop1");
|
||||
property.setObjectType(objectType);
|
||||
objectType.getProperties().add(property);
|
||||
tx.commit();
|
||||
}
|
||||
try (Session sess = openSession()) {
|
||||
Transaction tx = sess.beginTransaction();
|
||||
ObjectType objectType = sess.find(ObjectType.class, id);
|
||||
assertEquals(1, objectType.getProperties().size());
|
||||
tx.commit();
|
||||
}
|
||||
|
||||
try (Session sess = openSession()) {
|
||||
DataType dataType1 = sess.find(DataType.class, sId);
|
||||
assertTrue( dataType1 instanceof SimpleType );
|
||||
DataType dataType2 = sess.find(DataType.class, id);
|
||||
assertTrue( dataType2 instanceof ObjectType );
|
||||
}
|
||||
try (Session sess = openSession()) {
|
||||
SimpleType simpleType = sess.find(SimpleType.class, sId);
|
||||
}
|
||||
|
||||
try (Session sess = openSession()) {
|
||||
assertEquals( 2, sess.createQuery("from RepeatedTableTest$DataType").getResultList().size() );
|
||||
assertEquals( 1, sess.createQuery("from RepeatedTableTest$ObjectType").getResultList().size() );
|
||||
assertEquals( 1, sess.createQuery("from RepeatedTableTest$SimpleType").getResultList().size() );
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "DATA_TYPE")
|
||||
@Inheritance(strategy = JOINED)
|
||||
@DiscriminatorColumn(name = "supertype_id")
|
||||
@DiscriminatorOptions(force = true)
|
||||
public static abstract class DataType {
|
||||
|
||||
private Long id;
|
||||
private String name;
|
||||
|
||||
@Id
|
||||
@Column(name = "ID")
|
||||
@GeneratedValue
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Column(name = "name")
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Entity
|
||||
@DiscriminatorValue("8")
|
||||
@Table(name = "OBJ_TYPE")
|
||||
@PrimaryKeyJoinColumn(name = "TYPE_ID")
|
||||
public static class ObjectType extends DataType {
|
||||
|
||||
private String description;
|
||||
private List<Prop> properties;
|
||||
|
||||
@Column(name = "desc")
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@OneToMany(mappedBy = "objectType", cascade = ALL, orphanRemoval = true)
|
||||
public List<Prop> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public void setProperties(List<Prop> properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "PROP")
|
||||
public static class Prop {
|
||||
|
||||
private Long id;
|
||||
private String name;
|
||||
private ObjectType objectType;
|
||||
|
||||
@Id
|
||||
@Column(name = "ID")
|
||||
@GeneratedValue
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Column(name = "name")
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@JoinColumn(name = "OBJ_TYPE_ID")
|
||||
@ManyToOne
|
||||
public ObjectType getObjectType() {
|
||||
return objectType;
|
||||
}
|
||||
|
||||
public void setObjectType(ObjectType objectType) {
|
||||
this.objectType = objectType;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
@DiscriminatorValue("2")
|
||||
@Table(name = "DATA_TYPE")
|
||||
public static class SimpleType extends DataType {
|
||||
Integer count;
|
||||
|
||||
public Integer getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void setCount(Integer count) {
|
||||
this.count = count;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue