cleanups to AbstractCollectionPersister

Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
Gavin King 2024-11-09 21:06:20 +01:00
parent afa373f7c3
commit c86f151b7f

View File

@ -40,7 +40,6 @@
import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.IdentifierGenerator;
import org.hibernate.internal.FilterAliasGenerator; import org.hibernate.internal.FilterAliasGenerator;
import org.hibernate.internal.FilterHelper; import org.hibernate.internal.FilterHelper;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.jdbc.Expectation; import org.hibernate.jdbc.Expectation;
import org.hibernate.loader.ast.internal.CollectionElementLoaderByIndex; import org.hibernate.loader.ast.internal.CollectionElementLoaderByIndex;
import org.hibernate.loader.ast.internal.CollectionLoaderNamedQuery; import org.hibernate.loader.ast.internal.CollectionLoaderNamedQuery;
@ -50,20 +49,20 @@
import org.hibernate.loader.ast.spi.BatchLoaderFactory; import org.hibernate.loader.ast.spi.BatchLoaderFactory;
import org.hibernate.loader.ast.spi.CollectionLoader; import org.hibernate.loader.ast.spi.CollectionLoader;
import org.hibernate.mapping.Any; import org.hibernate.mapping.Any;
import org.hibernate.mapping.Array;
import org.hibernate.mapping.Collection; import org.hibernate.mapping.Collection;
import org.hibernate.mapping.Column; import org.hibernate.mapping.Column;
import org.hibernate.mapping.Formula; import org.hibernate.mapping.Formula;
import org.hibernate.mapping.IdentifierCollection; import org.hibernate.mapping.IdentifierCollection;
import org.hibernate.mapping.IndexedCollection; import org.hibernate.mapping.IndexedCollection;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Selectable; import org.hibernate.mapping.Selectable;
import org.hibernate.mapping.Table; import org.hibernate.mapping.Table;
import org.hibernate.mapping.Value; import org.hibernate.mapping.Value;
import org.hibernate.metamodel.CollectionClassification; import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.CollectionPart; import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.DiscriminatorConverter; import org.hibernate.metamodel.mapping.DiscriminatorMapping;
import org.hibernate.metamodel.mapping.DiscriminatorValueDetails; import org.hibernate.metamodel.mapping.DiscriminatorValueDetails;
import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
@ -74,7 +73,6 @@
import org.hibernate.metamodel.mapping.internal.EmbeddedCollectionPart; import org.hibernate.metamodel.mapping.internal.EmbeddedCollectionPart;
import org.hibernate.metamodel.mapping.internal.EntityCollectionPart; import org.hibernate.metamodel.mapping.internal.EntityCollectionPart;
import org.hibernate.metamodel.mapping.internal.InFlightCollectionMapping; import org.hibernate.metamodel.mapping.internal.InFlightCollectionMapping;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess; import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.metamodel.mapping.internal.PluralAttributeMappingImpl; import org.hibernate.metamodel.mapping.internal.PluralAttributeMappingImpl;
import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.metamodel.model.domain.NavigableRole;
@ -94,7 +92,6 @@
import org.hibernate.sql.Alias; import org.hibernate.sql.Alias;
import org.hibernate.sql.SimpleSelect; import org.hibernate.sql.SimpleSelect;
import org.hibernate.sql.Template; import org.hibernate.sql.Template;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SimpleFromClauseAccessImpl; import org.hibernate.sql.ast.spi.SimpleFromClauseAccessImpl;
import org.hibernate.sql.ast.spi.SqlAliasBaseConstant; import org.hibernate.sql.ast.spi.SqlAliasBaseConstant;
import org.hibernate.sql.ast.spi.SqlAliasBaseManager; import org.hibernate.sql.ast.spi.SqlAliasBaseManager;
@ -133,7 +130,6 @@
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -144,9 +140,16 @@
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.function.Consumer; import java.util.function.Consumer;
import static java.util.Collections.emptyList;
import static org.hibernate.internal.util.StringHelper.getNonEmptyOrConjunctionIfBothNonEmpty; import static org.hibernate.internal.util.StringHelper.getNonEmptyOrConjunctionIfBothNonEmpty;
import static org.hibernate.internal.util.StringHelper.isEmpty;
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
import static org.hibernate.internal.util.StringHelper.replace;
import static org.hibernate.internal.util.StringHelper.unqualify;
import static org.hibernate.internal.util.collections.CollectionHelper.arrayList; import static org.hibernate.internal.util.collections.CollectionHelper.arrayList;
import static org.hibernate.jdbc.Expectations.createExpectation; import static org.hibernate.jdbc.Expectations.createExpectation;
import static org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper.getTableIdentifierExpression;
import static org.hibernate.sql.Template.renderWhereStringTemplate;
import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER; import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER;
/** /**
@ -297,9 +300,9 @@ public AbstractCollectionPersister(
qualifiedTableName = determineTableName( table ); qualifiedTableName = determineTableName( table );
int spacesSize = 1 + collectionBootDescriptor.getSynchronizedTables().size(); final int spacesSize = 1 + collectionBootDescriptor.getSynchronizedTables().size();
spaces = new String[spacesSize]; spaces = new String[spacesSize];
Iterator<String> tables = collectionBootDescriptor.getSynchronizedTables().iterator(); final Iterator<String> tables = collectionBootDescriptor.getSynchronizedTables().iterator();
for ( int i = 1; i < spacesSize; i++ ) { for ( int i = 1; i < spacesSize; i++ ) {
spaces[i] = tables.next(); spaces[i] = tables.next();
} }
@ -315,7 +318,7 @@ public AbstractCollectionPersister(
// KEY // KEY
keyType = collectionBootDescriptor.getKey().getType(); keyType = collectionBootDescriptor.getKey().getType();
int keySpan = collectionBootDescriptor.getKey().getColumnSpan(); final int keySpan = collectionBootDescriptor.getKey().getColumnSpan();
keyColumnNames = new String[keySpan]; keyColumnNames = new String[keySpan];
keyColumnAliases = new String[keySpan]; keyColumnAliases = new String[keySpan];
int k = 0; int k = 0;
@ -330,19 +333,19 @@ public AbstractCollectionPersister(
// ELEMENT // ELEMENT
if ( elementType instanceof EntityType ) { if ( elementType instanceof EntityType entityType ) {
String entityName = ( (EntityType) elementType ).getAssociatedEntityName(); final String entityName = entityType.getAssociatedEntityName();
elementPersister = creationContext.getDomainModel().getEntityDescriptor( entityName ); elementPersister = creationContext.getDomainModel().getEntityDescriptor( entityName );
// NativeSQL: collect element column and auto-aliases // NativeSQL: collect element column and auto-aliases
} }
else { else {
elementPersister = null; elementPersister = null;
} }
// Defer this after the element persister was determined, because it is needed in OneToManyPersister#getTableName() // Defer this after the element persister was determined,
// because it is needed in OneToManyPersister.getTableName()
spaces[0] = getTableName(); spaces[0] = getTableName();
int elementSpan = elementBootDescriptor.getColumnSpan(); final int elementSpan = elementBootDescriptor.getColumnSpan();
elementColumnAliases = new String[elementSpan]; elementColumnAliases = new String[elementSpan];
elementColumnNames = new String[elementSpan]; elementColumnNames = new String[elementSpan];
elementColumnWriters = new String[elementSpan]; elementColumnWriters = new String[elementSpan];
@ -353,7 +356,7 @@ public AbstractCollectionPersister(
elementColumnIsSettable = new boolean[elementSpan]; elementColumnIsSettable = new boolean[elementSpan];
elementColumnIsGettable = new boolean[elementSpan]; elementColumnIsGettable = new boolean[elementSpan];
boolean isPureFormula = true; boolean isPureFormula = true;
boolean oneToMany = collectionBootDescriptor.isOneToMany(); final boolean oneToMany = collectionBootDescriptor.isOneToMany();
boolean[] columnInsertability = null; boolean[] columnInsertability = null;
if ( !oneToMany ) { if ( !oneToMany ) {
columnInsertability = elementBootDescriptor.getColumnInsertability(); columnInsertability = elementBootDescriptor.getColumnInsertability();
@ -400,11 +403,11 @@ public AbstractCollectionPersister(
final boolean hasIndex = collectionBootDescriptor.isIndexed(); final boolean hasIndex = collectionBootDescriptor.isIndexed();
if ( hasIndex ) { if ( hasIndex ) {
// NativeSQL: collect index column and auto-aliases // NativeSQL: collect index column and auto-aliases
IndexedCollection indexedCollection = (IndexedCollection) collectionBootDescriptor; final IndexedCollection indexedCollection = (IndexedCollection) collectionBootDescriptor;
indexType = indexedCollection.getIndex().getType(); indexType = indexedCollection.getIndex().getType();
int indexSpan = indexedCollection.getIndex().getColumnSpan(); final int indexSpan = indexedCollection.getIndex().getColumnSpan();
boolean[] indexColumnInsertability = indexedCollection.getIndex().getColumnInsertability(); final boolean[] indexColumnInsertability = indexedCollection.getIndex().getColumnInsertability();
boolean[] indexColumnUpdatability = indexedCollection.getIndex().getColumnUpdateability(); final boolean[] indexColumnUpdatability = indexedCollection.getIndex().getColumnUpdateability();
indexColumnNames = new String[indexSpan]; indexColumnNames = new String[indexSpan];
indexFormulaTemplates = new String[indexSpan]; indexFormulaTemplates = new String[indexSpan];
indexFormulas = new String[indexSpan]; indexFormulas = new String[indexSpan];
@ -413,10 +416,10 @@ public AbstractCollectionPersister(
indexColumnAliases = new String[indexSpan]; indexColumnAliases = new String[indexSpan];
int i = 0; int i = 0;
boolean hasFormula = false; boolean hasFormula = false;
for ( Selectable s: indexedCollection.getIndex().getSelectables() ) { for ( Selectable selectable: indexedCollection.getIndex().getSelectables() ) {
indexColumnAliases[i] = s.getAlias( dialect ); indexColumnAliases[i] = selectable.getAlias( dialect );
if ( s.isFormula() ) { if ( selectable.isFormula() ) {
Formula indexForm = (Formula) s; final Formula indexForm = (Formula) selectable;
indexFormulaTemplates[i] = indexForm.getTemplate( indexFormulaTemplates[i] = indexForm.getTemplate(
dialect, dialect,
creationContext.getTypeConfiguration(), creationContext.getTypeConfiguration(),
@ -430,15 +433,15 @@ public AbstractCollectionPersister(
// which enables optimizations for queries. The old insert/update code wasn't adapted yet though. // which enables optimizations for queries. The old insert/update code wasn't adapted yet though.
// For now, this is good enough, because the formula is never used anymore, // For now, this is good enough, because the formula is never used anymore,
// since all read paths go through the new code that can properly handle this case // since all read paths go through the new code that can properly handle this case
else if ( indexedCollection instanceof org.hibernate.mapping.Map else if ( indexedCollection instanceof org.hibernate.mapping.Map map
&& ( (org.hibernate.mapping.Map) indexedCollection ).getMapKeyPropertyName() != null ) { && map.getMapKeyPropertyName() != null ) {
Column indexCol = (Column) s; final Column indexCol = (Column) selectable;
indexFormulaTemplates[i] = Template.TEMPLATE + indexCol.getQuotedName( dialect ); indexFormulaTemplates[i] = Template.TEMPLATE + indexCol.getQuotedName( dialect );
indexFormulas[i] = indexCol.getQuotedName( dialect ); indexFormulas[i] = indexCol.getQuotedName( dialect );
hasFormula = true; hasFormula = true;
} }
else { else {
Column indexCol = (Column) s; final Column indexCol = (Column) selectable;
indexColumnNames[i] = indexCol.getQuotedName( dialect ); indexColumnNames[i] = indexCol.getQuotedName( dialect );
indexColumnIsGettable[i] = true; indexColumnIsGettable[i] = true;
indexColumnIsSettable[i] = indexColumnInsertability[i] || indexColumnUpdatability[i]; indexColumnIsSettable[i] = indexColumnInsertability[i] || indexColumnUpdatability[i];
@ -464,9 +467,9 @@ else if ( indexedCollection instanceof org.hibernate.mapping.Map
throw new MappingException( "one-to-many collections with identifiers are not supported" ); throw new MappingException( "one-to-many collections with identifiers are not supported" );
} }
//noinspection ConstantConditions //noinspection ConstantConditions
IdentifierCollection idColl = (IdentifierCollection) collectionBootDescriptor; final IdentifierCollection idColl = (IdentifierCollection) collectionBootDescriptor;
identifierType = idColl.getIdentifier().getType(); identifierType = idColl.getIdentifier().getType();
Column col = idColl.getIdentifier().getColumns().get(0); final Column col = idColl.getIdentifier().getColumns().get(0);
identifierColumnName = col.getQuotedName( dialect ); identifierColumnName = col.getQuotedName( dialect );
identifierColumnAlias = col.getAlias( dialect ); identifierColumnAlias = col.getAlias( dialect );
identifierGenerator = createGenerator( creationContext, idColl ); identifierGenerator = createGenerator( creationContext, idColl );
@ -485,8 +488,8 @@ else if ( indexedCollection instanceof org.hibernate.mapping.Map
keyIsUpdateable = collectionBootDescriptor.getKey().isUpdateable(); keyIsUpdateable = collectionBootDescriptor.getKey().isUpdateable();
if ( collectionBootDescriptor.isArray() ) { if ( collectionBootDescriptor instanceof Array arrayDescriptor ) {
elementClass = ( (org.hibernate.mapping.Array) collectionBootDescriptor ).getElementClass(); elementClass = arrayDescriptor.getElementClass();
} }
else { else {
// for non-arrays, we don't need to know the element class // for non-arrays, we don't need to know the element class
@ -515,20 +518,16 @@ else if ( indexedCollection instanceof org.hibernate.mapping.Map
} }
// Handle any filters applied to this collectionBinding for many-to-many // Handle any filters applied to this collectionBinding for many-to-many
if ( collectionBootDescriptor.getManyToManyFilters().isEmpty() ) { manyToManyFilterHelper = collectionBootDescriptor.getManyToManyFilters().isEmpty() ? null
manyToManyFilterHelper = null; : new FilterHelper( collectionBootDescriptor.getManyToManyFilters(), factory );
}
else {
manyToManyFilterHelper = new FilterHelper( collectionBootDescriptor.getManyToManyFilters(), factory);
}
if ( StringHelper.isEmpty( collectionBootDescriptor.getManyToManyWhere() ) ) { if ( isEmpty( collectionBootDescriptor.getManyToManyWhere() ) ) {
manyToManyWhereString = null; manyToManyWhereString = null;
manyToManyWhereTemplate = null; manyToManyWhereTemplate = null;
} }
else { else {
manyToManyWhereString = "( " + collectionBootDescriptor.getManyToManyWhere() + ")"; manyToManyWhereString = "( " + collectionBootDescriptor.getManyToManyWhere() + ")";
manyToManyWhereTemplate = Template.renderWhereStringTemplate( manyToManyWhereTemplate = renderWhereStringTemplate(
manyToManyWhereString, manyToManyWhereString,
creationContext.getDialect(), creationContext.getDialect(),
creationContext.getTypeConfiguration() creationContext.getTypeConfiguration()
@ -554,14 +553,12 @@ else if ( indexedCollection instanceof org.hibernate.mapping.Map
@Override @Override
public void prepareMappingModel(MappingModelCreationProcess creationProcess) { public void prepareMappingModel(MappingModelCreationProcess creationProcess) {
if ( mappedByProperty != null && elementType instanceof EntityType ) { if ( mappedByProperty != null && elementType instanceof EntityType entityType ) {
final String entityName = ((EntityType) elementType).getAssociatedEntityName(); final String entityName = entityType.getAssociatedEntityName();
final PersistentClass persistentClass =
final PersistentClass persistentClass = creationProcess.getCreationContext().getBootModel().getEntityBinding( entityName ); creationProcess.getCreationContext().getBootModel()
final Property property = persistentClass.getRecursiveProperty( mappedByProperty ); .getEntityBinding( entityName );
final Value propertyValue = property.getValue(); if ( persistentClass.getRecursiveProperty( mappedByProperty ).getValue() instanceof Any ) {
if ( propertyValue instanceof Any ) {
// we want to delay processing of where-fragment, and therefore affected SQL, until // we want to delay processing of where-fragment, and therefore affected SQL, until
// all model parts are ready so that we can access details about the ANY discriminator // all model parts are ready so that we can access details about the ANY discriminator
creationProcess.registerInitializationCallback( creationProcess.registerInitializationCallback(
@ -578,14 +575,11 @@ public void prepareMappingModel(MappingModelCreationProcess creationProcess) {
} }
} }
if ( StringHelper.isNotEmpty( collectionBootDescriptor.getWhere() ) ) { if ( isNotEmpty( collectionBootDescriptor.getWhere() ) ) {
hasWhere = true; hasWhere = true;
sqlWhereString = "(" + collectionBootDescriptor.getWhere() + ")"; sqlWhereString = "(" + collectionBootDescriptor.getWhere() + ")";
sqlWhereStringTemplate = Template.renderWhereStringTemplate( sqlWhereStringTemplate = renderWhereStringTemplate( sqlWhereString, dialect,
sqlWhereString, creationProcess.getCreationContext().getTypeConfiguration() );
dialect,
creationProcess.getCreationContext().getTypeConfiguration()
);
} }
buildStaticWhereFragmentSensitiveSql(); buildStaticWhereFragmentSensitiveSql();
collectionBootDescriptor = null; collectionBootDescriptor = null;
@ -596,33 +590,35 @@ private void delayedWhereFragmentProcessing(
String mappedByProperty, String mappedByProperty,
Collection collectionBootDescriptor, Collection collectionBootDescriptor,
MappingModelCreationProcess creationProcess) { MappingModelCreationProcess creationProcess) {
String where = collectionBootDescriptor.getWhere();
final AttributeMapping mappedByAttribute = resolveMappedBy( entityPersister, mappedByProperty, creationProcess ); final AttributeMapping mappedByAttribute = resolveMappedBy( entityPersister, mappedByProperty );
if ( mappedByAttribute instanceof DiscriminatedAssociationAttributeMapping ) { final RuntimeModelCreationContext creationContext = creationProcess.getCreationContext();
final DiscriminatedAssociationAttributeMapping anyMapping = (DiscriminatedAssociationAttributeMapping) mappedByAttribute; final String where;
final DiscriminatorConverter<?, ?> valueConverter = anyMapping.getDiscriminatorMapping().getValueConverter(); if ( mappedByAttribute instanceof DiscriminatedAssociationAttributeMapping anyMapping ) {
final DiscriminatorValueDetails discriminatorValueDetails = valueConverter.getDetailsForEntityName( ownerPersister.getEntityName() ); final DiscriminatorMapping discriminatorMapping = anyMapping.getDiscriminatorMapping();
final DiscriminatorValueDetails discriminatorValueDetails =
discriminatorMapping.getValueConverter()
.getDetailsForEntityName( ownerPersister.getEntityName() );
//noinspection unchecked //noinspection unchecked
final String discriminatorLiteral = anyMapping.getDiscriminatorMapping().getUnderlyingJdbcMapping().getJdbcLiteralFormatter().toJdbcLiteral( final String discriminatorLiteral =
discriminatorValueDetails.getValue(), discriminatorMapping.getUnderlyingJdbcMapping()
creationProcess.getCreationContext().getDialect(), .getJdbcLiteralFormatter().toJdbcLiteral(
creationProcess.getCreationContext().getSessionFactory().getWrapperOptions() discriminatorValueDetails.getValue(),
); creationContext.getDialect(),
where = getNonEmptyOrConjunctionIfBothNonEmpty( creationContext.getSessionFactory().getWrapperOptions()
where, );
anyMapping.getDiscriminatorMapping().getSelectableName() + "=" + discriminatorLiteral where = getNonEmptyOrConjunctionIfBothNonEmpty( collectionBootDescriptor.getWhere(),
); discriminatorMapping.getSelectableName() + "=" + discriminatorLiteral );
}
else {
where = collectionBootDescriptor.getWhere();
} }
if ( StringHelper.isNotEmpty( where ) ) { if ( isNotEmpty( where ) ) {
hasWhere = true; hasWhere = true;
sqlWhereString = "(" + where + ")"; sqlWhereString = "(" + where + ")";
sqlWhereStringTemplate = Template.renderWhereStringTemplate( sqlWhereStringTemplate = renderWhereStringTemplate( sqlWhereString, dialect,
sqlWhereString, creationContext.getTypeConfiguration() );
dialect,
creationProcess.getCreationContext().getTypeConfiguration()
);
} }
} }
@ -636,7 +632,7 @@ private boolean isMap() {
return collectionSemantics.getCollectionClassification().toJpaClassification() == PluralAttribute.CollectionType.MAP; return collectionSemantics.getCollectionClassification().toJpaClassification() == PluralAttribute.CollectionType.MAP;
} }
private static AttributeMapping resolveMappedBy(EntityPersister entityPersister, String mappedByProperty, MappingModelCreationProcess creationProcess) { private static AttributeMapping resolveMappedBy(EntityPersister entityPersister, String mappedByProperty) {
final StringTokenizer propertyPathParts = new StringTokenizer( mappedByProperty, ".", false ); final StringTokenizer propertyPathParts = new StringTokenizer( mappedByProperty, ".", false );
assert propertyPathParts.countTokens() > 0; assert propertyPathParts.countTokens() > 0;
@ -676,15 +672,12 @@ private BeforeExecutionGenerator createGenerator(RuntimeModelCreationContext con
} }
private boolean shouldUseShallowCacheLayout(CacheLayout collectionQueryCacheLayout, SessionFactoryOptions options) { private boolean shouldUseShallowCacheLayout(CacheLayout collectionQueryCacheLayout, SessionFactoryOptions options) {
final CacheLayout queryCacheLayout; final CacheLayout queryCacheLayout =
if ( collectionQueryCacheLayout == null ) { collectionQueryCacheLayout == null
queryCacheLayout = options.getQueryCacheLayout(); ? options.getQueryCacheLayout()
} : collectionQueryCacheLayout;
else { return queryCacheLayout == CacheLayout.SHALLOW
queryCacheLayout = collectionQueryCacheLayout; || queryCacheLayout == CacheLayout.AUTO && cacheAccessStrategy != null;
}
return queryCacheLayout == CacheLayout.SHALLOW || queryCacheLayout == CacheLayout.AUTO &&
cacheAccessStrategy != null;
} }
@Override @Override
@ -698,25 +691,20 @@ public Comparator<?> getSortingComparator() {
} }
protected String determineTableName(Table table) { protected String determineTableName(Table table) {
return MappingModelCreationHelper.getTableIdentifierExpression( table, factory ); return getTableIdentifierExpression( table, factory );
} }
@Override @Override
public void postInstantiate() throws MappingException { public void postInstantiate() throws MappingException {
if ( hasNamedQueryLoader() ) { collectionLoader =
// We pass null as metamodel because we did the initialization during construction already hasNamedQueryLoader()
collectionLoader = createNamedQueryCollectionLoader( this, getNamedQueryMemento( null ) ); // We pass null as metamodel because we did the initialization during construction already
} ? createNamedQueryCollectionLoader( this, getNamedQueryMemento( null ) )
else { : createCollectionLoader( new LoadQueryInfluencers( factory ) );
collectionLoader = createCollectionLoader( new LoadQueryInfluencers( factory ) );
}
if ( attributeMapping.getIndexDescriptor() != null ) { if ( attributeMapping.getIndexDescriptor() != null ) {
collectionElementLoaderByIndex = new CollectionElementLoaderByIndex( collectionElementLoaderByIndex =
attributeMapping, new CollectionElementLoaderByIndex( attributeMapping, new LoadQueryInfluencers( factory ), factory );
new LoadQueryInfluencers( factory ),
factory
);
} }
logStaticSQL(); logStaticSQL();
@ -734,33 +722,31 @@ private NamedQueryMemento<?> getNamedQueryMemento(MetadataImplementor bootModel)
} }
protected void logStaticSQL() { protected void logStaticSQL() {
if ( !ModelMutationLogging.MODEL_MUTATION_LOGGER.isDebugEnabled() ) { if ( ModelMutationLogging.MODEL_MUTATION_LOGGER.isDebugEnabled() ) {
return; MODEL_MUTATION_LOGGER.debugf( "Static SQL for collection: %s", getRole() );
}
MODEL_MUTATION_LOGGER.debugf( "Static SQL for collection: %s", getRole() ); final JdbcMutationOperation insertRowOperation = getRowMutationOperations().getInsertRowOperation();
final String insertRowSql = insertRowOperation != null ? insertRowOperation.getSqlString() : null;
if ( insertRowSql != null ) {
MODEL_MUTATION_LOGGER.debugf( " Row insert: %s", insertRowSql );
}
final JdbcMutationOperation insertRowOperation = getRowMutationOperations().getInsertRowOperation(); final JdbcMutationOperation updateRowOperation = getRowMutationOperations().getUpdateRowOperation();
final String insertRowSql = insertRowOperation != null ? insertRowOperation.getSqlString() : null; final String updateRowSql = updateRowOperation != null ? updateRowOperation.getSqlString() : null;
if ( insertRowSql != null ) { if ( updateRowSql != null ) {
MODEL_MUTATION_LOGGER.debugf( " Row insert: %s", insertRowSql ); MODEL_MUTATION_LOGGER.debugf( " Row update: %s", updateRowSql );
} }
final JdbcMutationOperation updateRowOperation = getRowMutationOperations().getUpdateRowOperation(); final JdbcMutationOperation deleteRowOperation = getRowMutationOperations().getDeleteRowOperation();
final String updateRowSql = updateRowOperation != null ? updateRowOperation.getSqlString() : null; final String deleteRowSql = deleteRowOperation != null ? deleteRowOperation.getSqlString() : null;
if ( updateRowSql != null ) { if ( deleteRowSql != null ) {
MODEL_MUTATION_LOGGER.debugf( " Row update: %s", updateRowSql ); MODEL_MUTATION_LOGGER.debugf( " Row delete: %s", deleteRowSql );
} }
final JdbcMutationOperation deleteRowOperation = getRowMutationOperations().getDeleteRowOperation(); final String deleteAllSql = getRemoveCoordinator().getSqlString();
final String deleteRowSql = deleteRowOperation != null ? deleteRowOperation.getSqlString() : null; if ( deleteAllSql != null ) {
if ( deleteRowSql != null ) { MODEL_MUTATION_LOGGER.debugf( " One-shot delete: %s", deleteAllSql );
MODEL_MUTATION_LOGGER.debugf( " Row delete: %s", deleteRowSql ); }
}
final String deleteAllSql = getRemoveCoordinator().getSqlString();
if ( deleteAllSql != null ) {
MODEL_MUTATION_LOGGER.debugf( " One-shot delete: %s", deleteAllSql );
} }
} }
@ -798,19 +784,18 @@ protected CollectionLoader determineLoaderToUse(Object key, SharedSessionContrac
// if there is a user-specified loader, return that // if there is a user-specified loader, return that
return getCollectionLoader(); return getCollectionLoader();
} }
else {
final LoadQueryInfluencers influencers = session.getLoadQueryInfluencers(); final LoadQueryInfluencers influencers = session.getLoadQueryInfluencers();
if ( influencers.effectiveSubselectFetchEnabled( this ) ) {
if ( influencers.effectiveSubselectFetchEnabled( this ) ) { final CollectionLoader subSelectLoader = resolveSubSelectLoader( key, session );
final CollectionLoader subSelectLoader = resolveSubSelectLoader( key, session ); if ( subSelectLoader != null ) {
if ( subSelectLoader != null ) { return subSelectLoader;
return subSelectLoader; }
} }
return attributeMapping.isAffectedByInfluencers( influencers, true )
? createCollectionLoader( influencers )
: getCollectionLoader();
} }
return attributeMapping.isAffectedByInfluencers( influencers, true )
? createCollectionLoader( influencers )
: getCollectionLoader();
} }
private CollectionLoader resolveSubSelectLoader(Object key, SharedSessionContractImplementor session) { private CollectionLoader resolveSubSelectLoader(Object key, SharedSessionContractImplementor session) {
@ -869,7 +854,8 @@ private CollectionLoader createCollectionLoader(LoadQueryInfluencers loadQueryIn
/** /**
* For Hibernate Reactive * For Hibernate Reactive
*/ */
protected CollectionLoader createNamedQueryCollectionLoader(CollectionPersister persister, NamedQueryMemento<?> namedQueryMemento) { protected CollectionLoader createNamedQueryCollectionLoader(
CollectionPersister persister, NamedQueryMemento<?> namedQueryMemento) {
return new CollectionLoaderNamedQuery(persister, namedQueryMemento); return new CollectionLoaderNamedQuery(persister, namedQueryMemento);
} }
@ -918,10 +904,7 @@ public Class<?> getElementClass() {
protected Object incrementIndexByBase(Object index) { protected Object incrementIndexByBase(Object index) {
final int baseIndex = attributeMapping.getIndexMetadata().getListIndexBase(); final int baseIndex = attributeMapping.getIndexMetadata().getListIndexBase();
if ( baseIndex > 0 ) { return baseIndex > 0 ? baseIndex + (Integer) index : index;
index = (Integer)index + baseIndex;
}
return index;
} }
@Override @Override
@ -936,12 +919,9 @@ public boolean isArray() {
@Override @Override
public String getIdentifierColumnName() { public String getIdentifierColumnName() {
if ( collectionSemantics.getCollectionClassification() == CollectionClassification.ID_BAG ) { return collectionSemantics.getCollectionClassification() == CollectionClassification.ID_BAG
return identifierColumnName; ? identifierColumnName
} : null;
else {
return null;
}
} }
/** /**
@ -1026,21 +1006,15 @@ public String selectFragment(String alias, String columnSuffix) {
); );
} }
final String sql = getFactory().getJdbcServices() final String sql =
.getDialect() getFactory().getJdbcServices().getDialect().getSqlAstTranslatorFactory()
.getSqlAstTranslatorFactory() .buildSelectTranslator( getFactory(), new SelectStatement( rootQuerySpec ) )
.buildSelectTranslator( getFactory(), new SelectStatement( rootQuerySpec ) ) .translate( null, QueryOptions.NONE )
.translate( null, QueryOptions.NONE ) .getSqlString();
.getSqlString();
final int fromIndex = sql.lastIndexOf( " from" ); final int fromIndex = sql.lastIndexOf( " from" );
final String expression; return fromIndex != -1
if ( fromIndex != -1 ) { ? sql.substring( "select ".length(), fromIndex )
expression = sql.substring( "select ".length(), fromIndex ); : sql.substring( "select ".length() );
}
else {
expression = sql.substring( "select ".length() );
}
return expression;
} }
protected String generateSelectSizeString(boolean isIntegerIndexed) { protected String generateSelectSizeString(boolean isIntegerIndexed) {
@ -1242,8 +1216,8 @@ private static void applyWhereFragments(Consumer<Predicate> predicateConsumer, S
return; return;
} }
final String fragment = StringHelper.replace( template, Template.TEMPLATE, alias ); final String fragment = replace( template, Template.TEMPLATE, alias );
if ( StringHelper.isEmpty( fragment ) ) { if ( isEmpty( fragment ) ) {
return; return;
} }
@ -1321,7 +1295,8 @@ public String getManyToManyFilterFragment(TableGroup tableGroup, Map<String, Fil
final StringBuilder fragment = new StringBuilder(); final StringBuilder fragment = new StringBuilder();
if ( manyToManyFilterHelper != null ) { if ( manyToManyFilterHelper != null ) {
manyToManyFilterHelper.render( fragment, elementPersister.getFilterAliasGenerator( tableGroup ), enabledFilters ); manyToManyFilterHelper.render( fragment,
elementPersister.getFilterAliasGenerator( tableGroup ), enabledFilters );
} }
if ( manyToManyWhereString != null ) { if ( manyToManyWhereString != null ) {
@ -1329,8 +1304,9 @@ public String getManyToManyFilterFragment(TableGroup tableGroup, Map<String, Fil
fragment.append( " and " ); fragment.append( " and " );
} }
assert elementPersister != null; assert elementPersister != null;
final TableReference tableReference = tableGroup.resolveTableReference( elementPersister.getTableName() ); fragment.append( replace( manyToManyWhereTemplate, Template.TEMPLATE,
fragment.append( StringHelper.replace( manyToManyWhereTemplate, Template.TEMPLATE, tableReference.getIdentificationVariable() ) ); tableGroup.resolveTableReference( elementPersister.getTableName() )
.getIdentificationVariable() ) );
} }
return fragment.toString(); return fragment.toString();
@ -1370,7 +1346,7 @@ public SessionFactoryImplementor getFactory() {
@Override @Override
public String toString() { public String toString() {
return StringHelper.unqualify( getClass().getName() ) + '(' + navigableRole.getFullPath() + ')'; return unqualify( getClass().getName() ) + '(' + navigableRole.getFullPath() + ')';
} }
@Override @Override
@ -1405,18 +1381,18 @@ public boolean isMutable() {
@Override @Override
public String[] getCollectionPropertyColumnAliases(String propertyName, String suffix) { public String[] getCollectionPropertyColumnAliases(String propertyName, String suffix) {
String[] rawAliases = collectionPropertyColumnAliases.get( propertyName ); final String[] rawAliases = collectionPropertyColumnAliases.get( propertyName );
if ( rawAliases == null ) { if ( rawAliases == null ) {
return null; return null;
} }
else {
String[] result = new String[rawAliases.length]; final String[] result = new String[rawAliases.length];
final Alias alias = new Alias( suffix ); final Alias alias = new Alias( suffix );
for ( int i = 0; i < rawAliases.length; i++ ) { for ( int i = 0; i < rawAliases.length; i++ ) {
result[i] = alias.toUnquotedAliasString( rawAliases[i] ); result[i] = alias.toUnquotedAliasString( rawAliases[i] );
}
return result;
} }
return result;
} }
// TODO: formulas ? // TODO: formulas ?
@ -1492,13 +1468,11 @@ public boolean elementExists(Object key, Object element, SharedSessionContractIm
private boolean exists(Object key, Object indexOrElement, Type indexOrElementType, String sql, SharedSessionContractImplementor session) { private boolean exists(Object key, Object indexOrElement, Type indexOrElementType, String sql, SharedSessionContractImplementor session) {
try { try {
final JdbcCoordinator jdbcCoordinator = session.getJdbcCoordinator(); final JdbcCoordinator jdbcCoordinator = session.getJdbcCoordinator();
PreparedStatement st = jdbcCoordinator final PreparedStatement st = jdbcCoordinator.getStatementPreparer().prepareStatement( sql );
.getStatementPreparer()
.prepareStatement( sql );
try { try {
getKeyType().nullSafeSet( st, key, 1, session ); getKeyType().nullSafeSet( st, key, 1, session );
indexOrElementType.nullSafeSet( st, indexOrElement, keyColumnNames.length + 1, session ); indexOrElementType.nullSafeSet( st, indexOrElement, keyColumnNames.length + 1, session );
ResultSet rs = jdbcCoordinator.getResultSetReturn().extract( st, sql ); final ResultSet rs = jdbcCoordinator.getResultSetReturn().extract( st, sql );
try { try {
return rs.next(); return rs.next();
} }
@ -1526,11 +1500,14 @@ private boolean exists(Object key, Object indexOrElement, Type indexOrElementTyp
@Override @Override
public Object getElementByIndex(Object key, Object index, SharedSessionContractImplementor session, Object owner) { public Object getElementByIndex(Object key, Object index, SharedSessionContractImplementor session, Object owner) {
if ( isAffectedByFilters( new HashSet<>(), attributeMapping.getElementDescriptor(), session.getLoadQueryInfluencers(), true ) ) { final LoadQueryInfluencers influencers = session.getLoadQueryInfluencers();
return new CollectionElementLoaderByIndex( attributeMapping, session.getLoadQueryInfluencers(), factory ) if ( isAffectedByFilters( new HashSet<>(), attributeMapping.getElementDescriptor(), influencers, true ) ) {
return new CollectionElementLoaderByIndex( attributeMapping, influencers, factory )
.load( key, index, session ); .load( key, index, session );
} }
return collectionElementLoaderByIndex.load( key, index, session ); else {
return collectionElementLoaderByIndex.load( key, index, session );
}
} }
@Override @Override
@ -1643,15 +1620,17 @@ private boolean isAffectedByFilters(
CollectionPart collectionPart, CollectionPart collectionPart,
LoadQueryInfluencers influencers, LoadQueryInfluencers influencers,
boolean onlyApplyForLoadByKey) { boolean onlyApplyForLoadByKey) {
if ( collectionPart instanceof EntityCollectionPart ) { if ( collectionPart instanceof EntityCollectionPart entityCollectionPart ) {
return ( (EntityCollectionPart) collectionPart ).getEntityMappingType() return entityCollectionPart.getEntityMappingType()
.isAffectedByEnabledFilters( visitedTypes, influencers, onlyApplyForLoadByKey ); .isAffectedByEnabledFilters( visitedTypes, influencers, onlyApplyForLoadByKey );
} }
else if ( collectionPart instanceof EmbeddedCollectionPart ) { else if ( collectionPart instanceof EmbeddedCollectionPart embeddedCollectionPart ) {
final EmbeddableMappingType type = ( (EmbeddedCollectionPart) collectionPart ).getEmbeddableTypeDescriptor(); final EmbeddableMappingType type = embeddedCollectionPart.getEmbeddableTypeDescriptor();
return type.isAffectedByEnabledFilters( visitedTypes, influencers, onlyApplyForLoadByKey ); return type.isAffectedByEnabledFilters( visitedTypes, influencers, onlyApplyForLoadByKey );
} }
return false; else {
return false;
}
} }
@Override @Override
@ -1743,22 +1722,17 @@ private static CollectionTableMapping buildCollectionTableMapping(
} }
protected JdbcMutationOperation buildDeleteAllOperation(MutatingTableReference tableReference) { protected JdbcMutationOperation buildDeleteAllOperation(MutatingTableReference tableReference) {
if ( tableMapping.getDeleteDetails().getCustomSql() != null ) { return tableMapping.getDeleteDetails().getCustomSql() != null
return buildCustomSqlDeleteAllOperation( tableReference ); ? buildCustomSqlDeleteAllOperation( tableReference )
} : buildGeneratedDeleteAllOperation( tableReference );
return buildGeneratedDeleteAllOperation( tableReference );
} }
private JdbcDeleteMutation buildCustomSqlDeleteAllOperation(MutatingTableReference tableReference) { private JdbcDeleteMutation buildCustomSqlDeleteAllOperation(MutatingTableReference tableReference) {
final PluralAttributeMapping attributeMapping = getAttributeMapping(); final PluralAttributeMapping attributeMapping = getAttributeMapping();
final ForeignKeyDescriptor keyDescriptor = attributeMapping.getKeyDescriptor(); final ForeignKeyDescriptor keyDescriptor = attributeMapping.getKeyDescriptor();
final ColumnValueParameterList parameterBinders = new ColumnValueParameterList( final ColumnValueParameterList parameterBinders =
tableReference, new ColumnValueParameterList( tableReference, ParameterUsage.RESTRICT, keyDescriptor.getJdbcTypeCount() );
ParameterUsage.RESTRICT,
keyDescriptor.getJdbcTypeCount()
);
keyDescriptor.getKeyPart().forEachSelectable( parameterBinders ); keyDescriptor.getKeyPart().forEachSelectable( parameterBinders );
final TableMapping tableMapping = tableReference.getTableMapping(); final TableMapping tableMapping = tableReference.getTableMapping();
@ -1773,14 +1747,9 @@ private JdbcDeleteMutation buildCustomSqlDeleteAllOperation(MutatingTableReferen
} }
private JdbcMutationOperation buildGeneratedDeleteAllOperation(MutatingTableReference tableReference) { private JdbcMutationOperation buildGeneratedDeleteAllOperation(MutatingTableReference tableReference) {
final RestrictedTableMutation<JdbcMutationOperation> sqlAst = generateDeleteAllAst( tableReference ); return getFactory().getJdbcServices().getDialect().getSqlAstTranslatorFactory()
.buildModelMutationTranslator( generateDeleteAllAst( tableReference ), getFactory() )
final SqlAstTranslator<JdbcMutationOperation> translator = getFactory().getJdbcServices() .translate( null, MutationQueryOptions.INSTANCE );
.getDialect()
.getSqlAstTranslatorFactory()
.buildModelMutationTranslator( sqlAst, getFactory() );
return translator.translate( null, MutationQueryOptions.INSTANCE );
} }
public RestrictedTableMutation<JdbcMutationOperation> generateDeleteAllAst(MutatingTableReference tableReference) { public RestrictedTableMutation<JdbcMutationOperation> generateDeleteAllAst(MutatingTableReference tableReference) {
@ -1790,11 +1759,8 @@ public RestrictedTableMutation<JdbcMutationOperation> generateDeleteAllAst(Mutat
assert fkDescriptor != null; assert fkDescriptor != null;
final int keyColumnCount = fkDescriptor.getJdbcTypeCount(); final int keyColumnCount = fkDescriptor.getJdbcTypeCount();
final ColumnValueParameterList parameterBinders = new ColumnValueParameterList( final ColumnValueParameterList parameterBinders =
tableReference, new ColumnValueParameterList( tableReference, ParameterUsage.RESTRICT, keyColumnCount );
ParameterUsage.RESTRICT,
keyColumnCount
);
final java.util.List<ColumnValueBinding> restrictionBindings = arrayList( keyColumnCount ); final java.util.List<ColumnValueBinding> restrictionBindings = arrayList( keyColumnCount );
applyKeyRestrictions( tableReference, parameterBinders, restrictionBindings ); applyKeyRestrictions( tableReference, parameterBinders, restrictionBindings );
@ -1804,7 +1770,7 @@ public RestrictedTableMutation<JdbcMutationOperation> generateDeleteAllAst(Mutat
this, this,
"one-shot delete for " + getRolePath(), "one-shot delete for " + getRolePath(),
restrictionBindings, restrictionBindings,
Collections.emptyList(), emptyList(),
parameterBinders, parameterBinders,
sqlWhereString sqlWhereString
); );