diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java index 7482ca6ad683..bfdcd4e7fbee 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java @@ -27,11 +27,9 @@ import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.mutation.ParameterUsage; import org.hibernate.engine.jdbc.mutation.internal.MutationQueryOptions; -import org.hibernate.engine.jdbc.spi.JdbcCoordinator; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.profile.internal.FetchProfileAffectee; import org.hibernate.engine.spi.LoadQueryInfluencers; -import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SubselectFetch; @@ -55,18 +53,12 @@ import org.hibernate.mapping.Formula; import org.hibernate.mapping.IdentifierCollection; import org.hibernate.mapping.IndexedCollection; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Selectable; import org.hibernate.mapping.Table; import org.hibernate.mapping.Value; import org.hibernate.metamodel.CollectionClassification; import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.CollectionPart; -import org.hibernate.metamodel.mapping.DiscriminatorMapping; -import org.hibernate.metamodel.mapping.DiscriminatorValueDetails; -import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; -import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.ManagedMappingType; import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.internal.DiscriminatedAssociationAttributeMapping; @@ -92,24 +84,20 @@ import org.hibernate.sql.Alias; import org.hibernate.sql.SimpleSelect; import org.hibernate.sql.Template; +import org.hibernate.sql.ast.SqlAstTranslatorFactory; import org.hibernate.sql.ast.spi.SimpleFromClauseAccessImpl; import org.hibernate.sql.ast.spi.SqlAliasBaseConstant; import org.hibernate.sql.ast.spi.SqlAliasBaseManager; import org.hibernate.sql.ast.spi.SqlAstCreationState; -import org.hibernate.sql.ast.spi.SqlSelection; import org.hibernate.sql.ast.tree.expression.AliasedExpression; -import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableReference; import org.hibernate.sql.ast.tree.predicate.Predicate; import org.hibernate.sql.ast.tree.select.QuerySpec; -import org.hibernate.sql.ast.tree.select.SelectClause; import org.hibernate.sql.ast.tree.select.SelectStatement; import org.hibernate.sql.model.MutationType; -import org.hibernate.sql.model.TableMapping; import org.hibernate.sql.model.TableMapping.MutationDetails; import org.hibernate.sql.model.ast.ColumnValueBinding; -import org.hibernate.sql.model.ast.ColumnValueParameter; import org.hibernate.sql.model.ast.ColumnValueParameterList; import org.hibernate.sql.model.ast.ColumnWriteFragment; import org.hibernate.sql.model.ast.MutatingTableReference; @@ -125,15 +113,13 @@ import org.hibernate.type.CompositeType; import org.hibernate.type.EntityType; import org.hibernate.type.Type; -import org.hibernate.type.spi.TypeConfiguration; -import java.sql.PreparedStatement; -import java.sql.ResultSet; import java.sql.SQLException; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; @@ -258,41 +244,36 @@ public abstract class AbstractCollectionPersister public AbstractCollectionPersister( Collection collectionBootDescriptor, @Nullable CollectionDataAccess cacheAccessStrategy, - RuntimeModelCreationContext creationContext) throws MappingException, CacheException { + RuntimeModelCreationContext creationContext) + throws MappingException, CacheException { + factory = creationContext.getSessionFactory(); + this.collectionBootDescriptor = collectionBootDescriptor; + this.collectionSemantics = + creationContext.getBootstrapContext().getMetadataBuildingOptions() + .getPersistentCollectionRepresentationResolver() + .resolveRepresentation( collectionBootDescriptor ); - this.factory = creationContext.getSessionFactory(); - this.collectionSemantics = creationContext.getBootstrapContext() - .getMetadataBuildingOptions() - .getPersistentCollectionRepresentationResolver() - .resolveRepresentation( collectionBootDescriptor ); this.cacheAccessStrategy = cacheAccessStrategy; - if ( creationContext.getSessionFactoryOptions().isStructuredCacheEntriesEnabled() ) { - cacheEntryStructure = collectionBootDescriptor.isMap() - ? StructuredMapCacheEntry.INSTANCE - : StructuredCollectionCacheEntry.INSTANCE; - } - else { - cacheEntryStructure = UnstructuredCacheEntry.INSTANCE; - } - useShallowQueryCacheLayout = shouldUseShallowCacheLayout( - collectionBootDescriptor.getQueryCacheLayout(), - creationContext.getSessionFactoryOptions() - ); + cacheEntryStructure = cacheEntryStructure( collectionBootDescriptor, creationContext ); + useShallowQueryCacheLayout = + shouldUseShallowCacheLayout( collectionBootDescriptor.getQueryCacheLayout(), + creationContext.getSessionFactoryOptions() ); dialect = creationContext.getDialect(); sqlExceptionHelper = creationContext.getJdbcServices().getSqlExceptionHelper(); collectionType = collectionBootDescriptor.getCollectionType(); navigableRole = new NavigableRole( collectionBootDescriptor.getRole() ); - ownerPersister = creationContext.getDomainModel() - .getEntityDescriptor( collectionBootDescriptor.getOwnerEntityName() ); + ownerPersister = + creationContext.getDomainModel() + .getEntityDescriptor( collectionBootDescriptor.getOwnerEntityName() ); queryLoaderName = collectionBootDescriptor.getLoaderName(); isMutable = collectionBootDescriptor.isMutable(); mappedByProperty = collectionBootDescriptor.getMappedByProperty(); - final Value elementBootDescriptor = collectionBootDescriptor.getElement(); - final Table table = collectionBootDescriptor.getCollectionTable(); + final var elementBootDescriptor = collectionBootDescriptor.getElement(); + final var table = collectionBootDescriptor.getCollectionTable(); elementType = elementBootDescriptor.getType(); // isSet = collectionBinding.isSet(); @@ -311,20 +292,20 @@ public AbstractCollectionPersister( hasOrphanDelete = collectionBootDescriptor.hasOrphanDelete(); - batchSize = collectionBootDescriptor.getBatchSize() < 0 - ? factory.getSessionFactoryOptions().getDefaultBatchFetchSize() - : collectionBootDescriptor.getBatchSize(); + batchSize = batchSize( collectionBootDescriptor, creationContext ); isVersioned = collectionBootDescriptor.isOptimisticLocked(); // KEY - keyType = collectionBootDescriptor.getKey().getType(); - final int keySpan = collectionBootDescriptor.getKey().getColumnSpan(); + final var key = collectionBootDescriptor.getKey(); + + keyType = key.getType(); + final int keySpan = key.getColumnSpan(); keyColumnNames = new String[keySpan]; keyColumnAliases = new String[keySpan]; int k = 0; - for ( Selectable selectable: collectionBootDescriptor.getKey().getSelectables() ) { + for ( var selectable: key.getSelectables() ) { // NativeSQL: collect key column and auto-aliases keyColumnAliases[k] = selectable.getAlias( dialect, table ); if ( selectable instanceof Column column ) { @@ -349,10 +330,10 @@ public AbstractCollectionPersister( elementPersister = null; } // Defer this after the element persister was determined, - // because it is needed in OneToManyPersister.getTableName() + // because it's needed in OneToManyPersister.getTableName() spaces[0] = getTableName(); - final TypeConfiguration typeConfiguration = creationContext.getTypeConfiguration(); + final var typeConfiguration = creationContext.getTypeConfiguration(); final int elementSpan = elementBootDescriptor.getColumnSpan(); elementColumnAliases = new String[elementSpan]; @@ -366,28 +347,23 @@ public AbstractCollectionPersister( elementColumnIsGettable = new boolean[elementSpan]; boolean isPureFormula = true; final boolean oneToMany = collectionBootDescriptor.isOneToMany(); - boolean[] columnInsertability = null; - if ( !oneToMany ) { - columnInsertability = elementBootDescriptor.getColumnInsertability(); - } + final boolean[] columnInsertability = oneToMany ? null : elementBootDescriptor.getColumnInsertability(); int j = 0; - for ( Selectable selectable: elementBootDescriptor.getSelectables() ) { + for ( var selectable: elementBootDescriptor.getSelectables() ) { elementColumnAliases[j] = selectable.getAlias( dialect, table ); - if ( selectable.isFormula() ) { - Formula form = (Formula) selectable; - elementFormulaTemplates[j] = form.getTemplate( dialect, typeConfiguration ); - elementFormulas[j] = form.getFormula(); + if ( selectable instanceof Formula formula ) { + elementFormulaTemplates[j] = formula.getTemplate( dialect, typeConfiguration ); + elementFormulas[j] = formula.getFormula(); } - else { - final Column col = (Column) selectable; - elementColumnNames[j] = col.getQuotedName( dialect ); - elementColumnWriters[j] = col.getWriteExpr( + else if ( selectable instanceof Column column ) { + elementColumnNames[j] = column.getQuotedName( dialect ); + elementColumnWriters[j] = column.getWriteExpr( elementBootDescriptor.getSelectableType( factory.getRuntimeMetamodels(), j ), dialect, creationContext.getBootModel() ); - elementColumnReaders[j] = col.getReadExpr( dialect ); - elementColumnReaderTemplates[j] = col.getTemplate( dialect, typeConfiguration ); + elementColumnReaders[j] = column.getReadExpr( dialect ); + elementColumnReaderTemplates[j] = column.getTemplate( dialect, typeConfiguration ); elementColumnIsGettable[j] = true; if ( elementType instanceof ComponentType || elementType instanceof AnyType ) { // Implements desired behavior specifically for @ElementCollection mappings. @@ -421,15 +397,14 @@ public AbstractCollectionPersister( indexColumnAliases = new String[indexSpan]; int i = 0; boolean hasFormula = false; - for ( Selectable selectable: index.getSelectables() ) { + for ( var selectable: index.getSelectables() ) { indexColumnAliases[i] = selectable.getAlias( dialect ); - if ( selectable.isFormula() ) { - final Formula indexForm = (Formula) selectable; - indexFormulaTemplates[i] = indexForm.getTemplate( dialect, typeConfiguration ); - indexFormulas[i] = indexForm.getFormula(); + if ( selectable instanceof Formula indexFormula ) { + indexFormulaTemplates[i] = indexFormula.getTemplate( dialect, typeConfiguration ); + indexFormulas[i] = indexFormula.getFormula(); hasFormula = true; } - else { + else if ( selectable instanceof Column indexColumn ) { if ( indexedCollection.hasMapKeyProperty() ) { // If the Map key is set via @MapKey, it should not be written // since it is a reference to a field of the associated entity. @@ -439,8 +414,7 @@ public AbstractCollectionPersister( indexColumnUpdatability[i] = false; hasFormula = true; // this is incorrect, but needed for some reason } - final Column indexCol = (Column) selectable; - indexColumnNames[i] = indexCol.getQuotedName( dialect ); + indexColumnNames[i] = indexColumn.getQuotedName( dialect ); indexColumnIsGettable[i] = true; indexColumnIsSettable[i] = indexColumnInsertability[i] || indexColumnUpdatability[i]; } @@ -465,12 +439,12 @@ public AbstractCollectionPersister( throw new MappingException( "one-to-many collections with identifiers are not supported" ); } //noinspection ConstantConditions - final IdentifierCollection idColl = (IdentifierCollection) collectionBootDescriptor; - identifierType = idColl.getIdentifier().getType(); - final Column col = idColl.getIdentifier().getColumns().get(0); - identifierColumnName = col.getQuotedName( dialect ); - identifierColumnAlias = col.getAlias( dialect ); - identifierGenerator = createGenerator( creationContext, idColl ); + final var idCollection = (IdentifierCollection) collectionBootDescriptor; + identifierType = idCollection.getIdentifier().getType(); + final var idColumn = idCollection.getIdentifier().getColumns().get(0); + identifierColumnName = idColumn.getQuotedName( dialect ); + identifierColumnAlias = idColumn.getAlias( dialect ); + identifierGenerator = createGenerator( creationContext, idCollection ); } else { identifierType = null; @@ -484,7 +458,7 @@ public AbstractCollectionPersister( isInverse = collectionBootDescriptor.isInverse(); - keyIsUpdateable = collectionBootDescriptor.getKey().isUpdateable(); + keyIsUpdateable = key.isUpdateable(); elementClass = collectionBootDescriptor instanceof Array arrayDescriptor @@ -496,33 +470,17 @@ public AbstractCollectionPersister( hasManyToManyOrder = collectionBootDescriptor.getManyToManyOrdering() != null; // Handle any filters applied to this collectionBinding - if ( collectionBootDescriptor.getFilters().isEmpty() ) { - filterHelper = null; - } - else { - final Map entityNameByTableNameMap; - if ( elementPersister == null ) { - entityNameByTableNameMap = null; - } - else { - entityNameByTableNameMap = AbstractEntityPersister.getEntityNameByTableNameMap( - creationContext.getBootModel().getEntityBinding( elementPersister.getEntityName() ), - factory.getSqlStringGenerationContext() - ); - } - filterHelper = new FilterHelper( collectionBootDescriptor.getFilters(), entityNameByTableNameMap, factory ); - } - + filterHelper = filterHelper( collectionBootDescriptor, elementPersister, creationContext ); // Handle any filters applied to this collectionBinding for many-to-many - manyToManyFilterHelper = collectionBootDescriptor.getManyToManyFilters().isEmpty() ? null - : new FilterHelper( collectionBootDescriptor.getManyToManyFilters(), factory ); + manyToManyFilterHelper = manyToManyFilterHelper( collectionBootDescriptor, creationContext ); - if ( isEmpty( collectionBootDescriptor.getManyToManyWhere() ) ) { + final String manyToManyWhere = collectionBootDescriptor.getManyToManyWhere(); + if ( isEmpty( manyToManyWhere ) ) { manyToManyWhereString = null; manyToManyWhereTemplate = null; } else { - manyToManyWhereString = "( " + collectionBootDescriptor.getManyToManyWhere() + ")"; + manyToManyWhereString = "( " + manyToManyWhere + ")"; manyToManyWhereTemplate = renderWhereStringTemplate( manyToManyWhereString, creationContext.getDialect(), typeConfiguration ); } @@ -540,15 +498,60 @@ public AbstractCollectionPersister( tableMapping = buildCollectionTableMapping( collectionBootDescriptor, getTableName(), getCollectionSpaces() ); - cascadeDeleteEnabled = collectionBootDescriptor.getKey().isCascadeDeleteEnabled() + cascadeDeleteEnabled = + key.isCascadeDeleteEnabled() && creationContext.getDialect().supportsCascadeDelete(); } + private FilterHelper manyToManyFilterHelper(Collection collection, RuntimeModelCreationContext context) { + return collection.getManyToManyFilters().isEmpty() + ? null + : new FilterHelper( collection.getManyToManyFilters(), context.getSessionFactory() ); + } + + private FilterHelper filterHelper( + Collection collection, EntityPersister elementPersister, RuntimeModelCreationContext context) { + if ( collection.getFilters().isEmpty() ) { + return null; + } + else { + final var entityNameByTableNameMap = + elementPersister == null + ? null + : AbstractEntityPersister.getEntityNameByTableNameMap( + context.getBootModel().getEntityBinding( elementPersister.getEntityName() ), + context.getSessionFactory().getSqlStringGenerationContext() + ); + return new FilterHelper( collection.getFilters(), entityNameByTableNameMap, factory ); + } + } + + private static int batchSize(Collection collection, RuntimeModelCreationContext context) { + return collection.getBatchSize() < 0 + ? context.getSessionFactoryOptions().getDefaultBatchFetchSize() + : collection.getBatchSize(); + } + + private static CacheEntryStructure cacheEntryStructure(Collection collection, RuntimeModelCreationContext context) { + if ( context.getSessionFactoryOptions().isStructuredCacheEntriesEnabled() ) { + return collection.isMap() + ? StructuredMapCacheEntry.INSTANCE + : StructuredCollectionCacheEntry.INSTANCE; + } + else { + return UnstructuredCacheEntry.INSTANCE; + } + } + + SqlAstTranslatorFactory getSqlAstTranslatorFactory() { + return getFactory().getJdbcServices().getDialect().getSqlAstTranslatorFactory(); + } + @Override public void prepareMappingModel(MappingModelCreationProcess creationProcess) { if ( mappedByProperty != null && elementType instanceof EntityType entityType ) { final String entityName = entityType.getAssociatedEntityName(); - final PersistentClass persistentClass = + final var persistentClass = creationProcess.getCreationContext().getBootModel() .getEntityBinding( entityName ); if ( persistentClass.getRecursiveProperty( mappedByProperty ).getValue() instanceof Any ) { @@ -557,8 +560,12 @@ public void prepareMappingModel(MappingModelCreationProcess creationProcess) { creationProcess.registerInitializationCallback( "Where-fragment handling for ANY inverse mapping : " + navigableRole, () -> { - final EntityPersister entityPersister = creationProcess.getEntityPersister( entityName ); - delayedWhereFragmentProcessing( entityPersister, mappedByProperty, collectionBootDescriptor, creationProcess ); + delayedWhereFragmentProcessing( + creationProcess.getEntityPersister( entityName ), + mappedByProperty, + collectionBootDescriptor, + creationProcess + ); buildStaticWhereFragmentSensitiveSql(); collectionBootDescriptor = null; return true; @@ -571,8 +578,9 @@ public void prepareMappingModel(MappingModelCreationProcess creationProcess) { if ( isNotEmpty( collectionBootDescriptor.getWhere() ) ) { hasWhere = true; sqlWhereString = "(" + collectionBootDescriptor.getWhere() + ")"; - sqlWhereStringTemplate = renderWhereStringTemplate( sqlWhereString, dialect, - creationProcess.getCreationContext().getTypeConfiguration() ); + sqlWhereStringTemplate = + renderWhereStringTemplate( sqlWhereString, dialect, + creationProcess.getCreationContext().getTypeConfiguration() ); } buildStaticWhereFragmentSensitiveSql(); collectionBootDescriptor = null; @@ -584,14 +592,14 @@ private void delayedWhereFragmentProcessing( Collection collectionBootDescriptor, MappingModelCreationProcess creationProcess) { - final AttributeMapping mappedByAttribute = resolveMappedBy( entityPersister, mappedByProperty ); - final RuntimeModelCreationContext creationContext = creationProcess.getCreationContext(); final String where; - if ( mappedByAttribute instanceof DiscriminatedAssociationAttributeMapping anyMapping ) { - final DiscriminatorMapping discriminatorMapping = anyMapping.getDiscriminatorMapping(); - final DiscriminatorValueDetails discriminatorValueDetails = + if ( resolveMappedBy( entityPersister, mappedByProperty ) + instanceof DiscriminatedAssociationAttributeMapping anyMapping ) { + final var discriminatorMapping = anyMapping.getDiscriminatorMapping(); + final var discriminatorValueDetails = discriminatorMapping.getValueConverter() .getDetailsForEntityName( ownerPersister.getEntityName() ); + final var creationContext = creationProcess.getCreationContext(); //noinspection unchecked final String discriminatorLiteral = discriminatorMapping.getUnderlyingJdbcMapping() @@ -610,8 +618,9 @@ private void delayedWhereFragmentProcessing( if ( isNotEmpty( where ) ) { hasWhere = true; sqlWhereString = "(" + where + ")"; - sqlWhereStringTemplate = renderWhereStringTemplate( sqlWhereString, dialect, - creationContext.getTypeConfiguration() ); + sqlWhereStringTemplate = + renderWhereStringTemplate( sqlWhereString, dialect, + creationProcess.getCreationContext().getTypeConfiguration() ); } } @@ -626,32 +635,31 @@ private boolean isMap() { } private static AttributeMapping resolveMappedBy(EntityPersister entityPersister, String mappedByProperty) { - final StringTokenizer propertyPathParts = new StringTokenizer( mappedByProperty, ".", false ); - assert propertyPathParts.countTokens() > 0; - - if ( propertyPathParts.countTokens() == 1 ) { + final var propertyPathParts = new StringTokenizer( mappedByProperty, ".", false ); + final int tokenCount = propertyPathParts.countTokens(); + assert tokenCount > 0; + if ( tokenCount == 1 ) { return entityPersister.findAttributeMapping( propertyPathParts.nextToken() ); } - - ManagedMappingType source = entityPersister; - while ( propertyPathParts.hasMoreTokens() ) { - final String partName = propertyPathParts.nextToken(); - final AttributeMapping namedPart = source.findAttributeMapping( partName ); - if ( !propertyPathParts.hasMoreTokens() ) { - return namedPart; + else { + ManagedMappingType source = entityPersister; + while ( propertyPathParts.hasMoreTokens() ) { + final String partName = propertyPathParts.nextToken(); + final var namedPart = source.findAttributeMapping( partName ); + if ( !propertyPathParts.hasMoreTokens() ) { + return namedPart; + } + source = (ManagedMappingType) namedPart.getPartMappingType(); } - - source = (ManagedMappingType) namedPart.getPartMappingType(); + throw new MappingException( + String.format( + Locale.ROOT, + "Unable to resolve mapped-by path : (%s) %s", + entityPersister.getEntityName(), + mappedByProperty + ) + ); } - - throw new MappingException( - String.format( - Locale.ROOT, - "Unable to resolve mapped-by path : (%s) %s", - entityPersister.getEntityName(), - mappedByProperty - ) - ); } private BeforeExecutionGenerator createGenerator(RuntimeModelCreationContext context, IdentifierCollection collection) { @@ -665,7 +673,7 @@ private BeforeExecutionGenerator createGenerator(RuntimeModelCreationContext con } private boolean shouldUseShallowCacheLayout(CacheLayout collectionQueryCacheLayout, SessionFactoryOptions options) { - final CacheLayout queryCacheLayout = + final var queryCacheLayout = collectionQueryCacheLayout == null ? options.getQueryCacheLayout() : collectionQueryCacheLayout; @@ -704,7 +712,7 @@ public void postInstantiate() throws MappingException { } private NamedQueryMemento getNamedQueryMemento(MetadataImplementor bootModel) { - final NamedQueryMemento memento = + final var memento = factory.getQueryEngine().getNamedObjectRepository() .resolve( factory, bootModel, queryLoaderName ); if ( memento == null ) { @@ -718,19 +726,21 @@ protected void logStaticSQL() { if ( MODEL_MUTATION_LOGGER.isTraceEnabled() ) { MODEL_MUTATION_LOGGER.tracef( "Static SQL for collection: %s", getRole() ); - final JdbcMutationOperation insertRowOperation = getRowMutationOperations().getInsertRowOperation(); + final var rowMutationOperations = getRowMutationOperations(); + + final var insertRowOperation = rowMutationOperations.getInsertRowOperation(); final String insertRowSql = insertRowOperation != null ? insertRowOperation.getSqlString() : null; if ( insertRowSql != null ) { MODEL_MUTATION_LOGGER.tracef( " Row insert: %s", insertRowSql ); } - final JdbcMutationOperation updateRowOperation = getRowMutationOperations().getUpdateRowOperation(); + final var updateRowOperation = rowMutationOperations.getUpdateRowOperation(); final String updateRowSql = updateRowOperation != null ? updateRowOperation.getSqlString() : null; if ( updateRowSql != null ) { MODEL_MUTATION_LOGGER.tracef( " Row update: %s", updateRowSql ); } - final JdbcMutationOperation deleteRowOperation = getRowMutationOperations().getDeleteRowOperation(); + final var deleteRowOperation = rowMutationOperations.getDeleteRowOperation(); final String deleteRowSql = deleteRowOperation != null ? deleteRowOperation.getSqlString() : null; if ( deleteRowSql != null ) { MODEL_MUTATION_LOGGER.tracef( " Row delete: %s", deleteRowSql ); @@ -778,9 +788,9 @@ protected CollectionLoader determineLoaderToUse(Object key, SharedSessionContrac return getCollectionLoader(); } else { - final LoadQueryInfluencers influencers = session.getLoadQueryInfluencers(); + final var influencers = session.getLoadQueryInfluencers(); if ( influencers.effectiveSubselectFetchEnabled( this ) ) { - final CollectionLoader subSelectLoader = resolveSubSelectLoader( key, session ); + final var subSelectLoader = resolveSubSelectLoader( key, session ); if ( subSelectLoader != null ) { return subSelectLoader; } @@ -792,8 +802,8 @@ protected CollectionLoader determineLoaderToUse(Object key, SharedSessionContrac } private CollectionLoader resolveSubSelectLoader(Object key, SharedSessionContractImplementor session) { - final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); - final SubselectFetch subselect = + final var persistenceContext = session.getPersistenceContextInternal(); + final var subselect = persistenceContext.getBatchFetchQueue() .getSubselect( session.generateEntityKey( key, getOwnerEntityPersister() ) ); if ( subselect == null ) { @@ -920,9 +930,9 @@ public String getIdentifierColumnName() { */ @Override public String selectFragment(String alias, String columnSuffix) { - final PluralAttributeMapping attributeMapping = getAttributeMapping(); - final QuerySpec rootQuerySpec = new QuerySpec( true ); - final LoaderSqlAstCreationState sqlAstCreationState = new LoaderSqlAstCreationState( + final var attributeMapping = getAttributeMapping(); + final var rootQuerySpec = new QuerySpec( true ); + final var sqlAstCreationState = new LoaderSqlAstCreationState( rootQuerySpec, new SqlAliasBaseManager(), new SimpleFromClauseAccessImpl(), @@ -933,8 +943,8 @@ public String selectFragment(String alias, String columnSuffix) { factory.getSqlTranslationEngine() ); - final NavigablePath entityPath = new NavigablePath( attributeMapping.getRootPathName() ); - final TableGroup rootTableGroup = attributeMapping.createRootTableGroup( + final var entityPath = new NavigablePath( attributeMapping.getRootPathName() ); + final var rootTableGroup = attributeMapping.createRootTableGroup( true, entityPath, null, @@ -949,15 +959,15 @@ public String selectFragment(String alias, String columnSuffix) { attributeMapping.createDomainResult( entityPath, rootTableGroup, null, sqlAstCreationState ); // Wrap expressions with aliases - final SelectClause selectClause = rootQuerySpec.getSelectClause(); - final java.util.List sqlSelections = selectClause.getSqlSelections(); + final var sqlSelections = rootQuerySpec.getSelectClause().getSqlSelections(); int i = 0; for ( String keyAlias : keyColumnAliases ) { sqlSelections.set( i, new SqlSelectionImpl( i, - new AliasedExpression( sqlSelections.get( i ).getExpression(), keyAlias + columnSuffix ) + new AliasedExpression( sqlSelections.get( i ).getExpression(), + keyAlias + columnSuffix ) ) ); i++; @@ -969,7 +979,8 @@ public String selectFragment(String alias, String columnSuffix) { i, new SqlSelectionImpl( i, - new AliasedExpression( sqlSelections.get( i ).getExpression(), indexAlias + columnSuffix ) + new AliasedExpression( sqlSelections.get( i ).getExpression(), + indexAlias + columnSuffix ) ) ); i++; @@ -980,25 +991,27 @@ public String selectFragment(String alias, String columnSuffix) { i, new SqlSelectionImpl( i, - new AliasedExpression( sqlSelections.get( i ).getExpression(), identifierColumnAlias + columnSuffix ) + new AliasedExpression( sqlSelections.get( i ).getExpression(), + identifierColumnAlias + columnSuffix ) ) ); i++; } for ( int columnIndex = 0; i < sqlSelections.size(); i++, columnIndex++ ) { - final SqlSelection sqlSelection = sqlSelections.get( i ); + final var sqlSelection = sqlSelections.get( i ); sqlSelections.set( i, new SqlSelectionImpl( sqlSelection.getValuesArrayPosition(), - new AliasedExpression( sqlSelection.getExpression(), elementColumnAliases[columnIndex] + columnSuffix ) + new AliasedExpression( sqlSelection.getExpression(), + elementColumnAliases[columnIndex] + columnSuffix ) ) ); } final String sql = - getFactory().getJdbcServices().getDialect().getSqlAstTranslatorFactory() + getSqlAstTranslatorFactory() .buildSelectTranslator( getFactory(), new SelectStatement( rootQuerySpec ) ) .translate( null, QueryOptions.NONE ) .getSqlString(); @@ -1009,9 +1022,9 @@ public String selectFragment(String alias, String columnSuffix) { } protected String generateSelectSizeString(boolean isIntegerIndexed) { - String selectValue = isIntegerIndexed ? - "max(" + getIndexColumnNames()[0] + ") + 1" : // lists, arrays - "count(" + getElementColumnNames()[0] + ")"; // sets, maps, bags + final String selectValue = isIntegerIndexed + ? "max(" + getIndexColumnNames()[0] + ") + 1" // lists, arrays + : "count(" + getElementColumnNames()[0] + ")"; // sets, maps, bags return new SimpleSelect( getFactory() ) .setTableName( getTableName() ) .addRestriction( getKeyColumnNames() ) @@ -1024,14 +1037,16 @@ protected String generateDetectRowByIndexString() { if ( !hasIndex() ) { return null; } - return new SimpleSelect( getFactory() ) - .setTableName( getTableName() ) - .addRestriction( getKeyColumnNames() ) - .addRestriction( getIndexColumnNames() ) - .addRestriction( indexFormulas ) - .addWhereToken( sqlWhereString ) - .addColumn( "1" ) - .toStatementString(); + else { + return new SimpleSelect( getFactory() ) + .setTableName( getTableName() ) + .addRestriction( getKeyColumnNames() ) + .addRestriction( getIndexColumnNames() ) + .addRestriction( indexFormulas ) + .addWhereToken( sqlWhereString ) + .addColumn( "1" ) + .toStatementString(); + } } @@ -1164,34 +1179,30 @@ public boolean hasWhereRestrictions() { return hasWhere || manyToManyWhereTemplate != null; } - @Override - public void applyWhereRestrictions( - Consumer predicateConsumer, - TableGroup tableGroup, - boolean useQualifier, - SqlAstCreationState creationState) { - final TableReference tableReference; - if ( isManyToMany() ) { - tableReference = tableGroup.getPrimaryTableReference(); - } - else if ( elementPersister != null ) { - tableReference = tableGroup.getTableReference( tableGroup.getNavigablePath(), elementPersister.getTableName() ); - } - else { - tableReference = tableGroup.getTableReference( tableGroup.getNavigablePath(), qualifiedTableName ); - } - - final String alias; + private static String aliasForWhereRestriction(TableReference tableReference, boolean useQualifier) { if ( tableReference == null ) { - alias = null; + return null; } else if ( useQualifier && tableReference.getIdentificationVariable() != null ) { - alias = tableReference.getIdentificationVariable(); + return tableReference.getIdentificationVariable(); } else { - alias = tableReference.getTableId(); + return tableReference.getTableId(); } + } + @Override + public void applyWhereRestrictions( + Consumer predicateConsumer, + TableGroup tableGroup, + boolean useQualifier, + SqlAstCreationState creationState) { + final var tableReference = + isManyToMany() + ? tableGroup.getPrimaryTableReference() + : tableGroup.getTableReference( tableGroup.getNavigablePath(), + elementPersister != null ? elementPersister.getTableName() : qualifiedTableName ); + final String alias = aliasForWhereRestriction( tableReference, useQualifier ); applyWhereFragments( predicateConsumer, alias, tableGroup, creationState ); } @@ -1207,16 +1218,12 @@ protected void applyWhereFragments( * Applies all defined {@link org.hibernate.annotations.SQLRestriction} */ private static void applyWhereFragments(Consumer predicateConsumer, String alias, String template) { - if ( template == null ) { - return; - } - - final String fragment = replace( template, Template.TEMPLATE, alias ); - if ( isEmpty( fragment ) ) { - return; + if ( template != null ) { + final String fragment = replace( template, Template.TEMPLATE, alias ); + if ( !isEmpty( fragment ) ) { + predicateConsumer.accept( new SqlFragmentPredicate( fragment ) ); + } } - - predicateConsumer.accept( new SqlFragmentPredicate( fragment ) ); } @Override @@ -1250,50 +1257,32 @@ public void applyBaseManyToManyRestrictions( Map enabledFilters, Set treatAsDeclarations, SqlAstCreationState creationState) { - if ( manyToManyFilterHelper == null && manyToManyWhereTemplate == null ) { - return; - } - - - if ( manyToManyFilterHelper != null ) { - final FilterAliasGenerator aliasGenerator = elementPersister.getFilterAliasGenerator( tableGroup ); - manyToManyFilterHelper.applyEnabledFilters( - predicateConsumer, - aliasGenerator, - enabledFilters, - false, - tableGroup, - creationState - ); - } - - if ( manyToManyWhereString != null ) { - final TableReference tableReference = tableGroup.resolveTableReference( elementPersister.getTableName() ); - - final String alias; - if ( tableReference == null ) { - alias = null; + if ( manyToManyFilterHelper != null || manyToManyWhereTemplate != null ) { + if ( manyToManyFilterHelper != null ) { + manyToManyFilterHelper.applyEnabledFilters( + predicateConsumer, + elementPersister.getFilterAliasGenerator( tableGroup ), + enabledFilters, + false, + tableGroup, + creationState + ); } - else if ( useQualifier && tableReference.getIdentificationVariable() != null ) { - alias = tableReference.getIdentificationVariable(); + if ( manyToManyWhereString != null ) { + final var tableReference = tableGroup.resolveTableReference( elementPersister.getTableName() ); + final String alias = aliasForWhereRestriction( tableReference, useQualifier ); + applyWhereFragments( predicateConsumer, alias, manyToManyWhereTemplate ); } - else { - alias = tableReference.getTableId(); - } - - applyWhereFragments( predicateConsumer, alias, manyToManyWhereTemplate ); } } @Override public String getManyToManyFilterFragment(TableGroup tableGroup, Map enabledFilters) { - final StringBuilder fragment = new StringBuilder(); - + final var fragment = new StringBuilder(); if ( manyToManyFilterHelper != null ) { manyToManyFilterHelper.render( fragment, elementPersister.getFilterAliasGenerator( tableGroup ), enabledFilters ); } - if ( manyToManyWhereString != null ) { if ( !fragment.isEmpty() ) { fragment.append( " and " ); @@ -1303,7 +1292,6 @@ public String getManyToManyFilterFragment(TableGroup tableGroup, Map(), attributeMapping.getElementDescriptor(), influencers, true ) ) { return new CollectionElementLoaderByIndex( attributeMapping, influencers, factory ) .load( key, index, session ); @@ -1576,10 +1563,10 @@ public boolean isAffectedByEnabledFilters(LoadQueryInfluencers influencers) { @Override public boolean isAffectedByEnabledFilters(LoadQueryInfluencers influencers, boolean onlyApplyForLoadByKeyFilters) { if ( influencers.hasEnabledFilters() ) { - final Map enabledFilters = influencers.getEnabledFilters(); + final var enabledFilters = influencers.getEnabledFilters(); return filterHelper != null && filterHelper.isAffectedBy( enabledFilters ) - || manyToManyFilterHelper != null && manyToManyFilterHelper.isAffectedBy( enabledFilters ) - || isKeyOrElementAffectedByFilters( new HashSet<>(), influencers, onlyApplyForLoadByKeyFilters); + || manyToManyFilterHelper != null && manyToManyFilterHelper.isAffectedBy( enabledFilters ) + || isKeyOrElementAffectedByFilters( new HashSet<>(), influencers, onlyApplyForLoadByKeyFilters); } else { return false; @@ -1592,10 +1579,10 @@ public boolean isAffectedByEnabledFilters( LoadQueryInfluencers influencers, boolean onlyApplyForLoadByKeyFilters) { if ( influencers.hasEnabledFilters() ) { - final Map enabledFilters = influencers.getEnabledFilters(); + final var enabledFilters = influencers.getEnabledFilters(); return filterHelper != null && filterHelper.isAffectedBy( enabledFilters ) - || manyToManyFilterHelper != null && manyToManyFilterHelper.isAffectedBy( enabledFilters ) - || isKeyOrElementAffectedByFilters( visitedTypes, influencers, onlyApplyForLoadByKeyFilters); + || manyToManyFilterHelper != null && manyToManyFilterHelper.isAffectedBy( enabledFilters ) + || isKeyOrElementAffectedByFilters( visitedTypes, influencers, onlyApplyForLoadByKeyFilters); } else { return false; @@ -1607,7 +1594,7 @@ private boolean isKeyOrElementAffectedByFilters( LoadQueryInfluencers influencers, boolean onlyApplyForLoadByKey) { return isAffectedByFilters( visitedTypes, attributeMapping.getIndexDescriptor(), influencers, onlyApplyForLoadByKey ) - || isAffectedByFilters( visitedTypes, attributeMapping.getElementDescriptor(), influencers, onlyApplyForLoadByKey ); + || isAffectedByFilters( visitedTypes, attributeMapping.getElementDescriptor(), influencers, onlyApplyForLoadByKey ); } private boolean isAffectedByFilters( @@ -1620,8 +1607,8 @@ private boolean isAffectedByFilters( .isAffectedByEnabledFilters( visitedTypes, influencers, onlyApplyForLoadByKey ); } else if ( collectionPart instanceof EmbeddedCollectionPart embeddedCollectionPart ) { - final EmbeddableMappingType type = embeddedCollectionPart.getEmbeddableTypeDescriptor(); - return type.isAffectedByEnabledFilters( visitedTypes, influencers, onlyApplyForLoadByKey ); + return embeddedCollectionPart.getEmbeddableTypeDescriptor() + .isAffectedByEnabledFilters( visitedTypes, influencers, onlyApplyForLoadByKey ); } else { return false; @@ -1723,14 +1710,12 @@ protected JdbcMutationOperation buildDeleteAllOperation(MutatingTableReference t } private JdbcDeleteMutation buildCustomSqlDeleteAllOperation(MutatingTableReference tableReference) { - final PluralAttributeMapping attributeMapping = getAttributeMapping(); - final ForeignKeyDescriptor keyDescriptor = attributeMapping.getKeyDescriptor(); - - final ColumnValueParameterList parameterBinders = + final var attributeMapping = getAttributeMapping(); + final var keyDescriptor = attributeMapping.getKeyDescriptor(); + final var parameterBinders = new ColumnValueParameterList( tableReference, ParameterUsage.RESTRICT, keyDescriptor.getJdbcTypeCount() ); keyDescriptor.getKeyPart().forEachSelectable( parameterBinders ); - - final TableMapping tableMapping = tableReference.getTableMapping(); + final var tableMapping = tableReference.getTableMapping(); return new JdbcDeleteMutation( tableMapping, this, @@ -1742,23 +1727,20 @@ private JdbcDeleteMutation buildCustomSqlDeleteAllOperation(MutatingTableReferen } private JdbcMutationOperation buildGeneratedDeleteAllOperation(MutatingTableReference tableReference) { - return getFactory().getJdbcServices().getDialect().getSqlAstTranslatorFactory() + return getSqlAstTranslatorFactory() .buildModelMutationTranslator( generateDeleteAllAst( tableReference ), getFactory() ) .translate( null, MutationQueryOptions.INSTANCE ); } public RestrictedTableMutation generateDeleteAllAst(MutatingTableReference tableReference) { assert getAttributeMapping() != null; - - final ForeignKeyDescriptor fkDescriptor = getAttributeMapping().getKeyDescriptor(); - assert fkDescriptor != null; - - final int keyColumnCount = fkDescriptor.getJdbcTypeCount(); - final ColumnValueParameterList parameterBinders = + final var foreignKeyDescriptor = getAttributeMapping().getKeyDescriptor(); + assert foreignKeyDescriptor != null; + final int keyColumnCount = foreignKeyDescriptor.getJdbcTypeCount(); + final var parameterBinders = new ColumnValueParameterList( tableReference, ParameterUsage.RESTRICT, keyColumnCount ); - final java.util.List restrictionBindings = arrayList( keyColumnCount ); - applyKeyRestrictions( tableReference, parameterBinders, restrictionBindings ); - + final List restrictionBindings = arrayList( keyColumnCount ); + applyKeyRestrictions( parameterBinders, restrictionBindings ); //noinspection unchecked,rawtypes return (RestrictedTableMutation) new TableDeleteStandard( tableReference, @@ -1772,16 +1754,13 @@ public RestrictedTableMutation generateDeleteAllAst(Mutat } protected void applyKeyRestrictions( - MutatingTableReference tableReference, ColumnValueParameterList parameterList, - java.util.List restrictionBindings) { - - final ForeignKeyDescriptor fkDescriptor = getAttributeMapping().getKeyDescriptor(); - assert fkDescriptor != null; - - fkDescriptor.getKeyPart().forEachSelectable( parameterList ); - for ( ColumnValueParameter columnValueParameter : parameterList ) { - final ColumnReference columnReference = columnValueParameter.getColumnReference(); + List restrictionBindings) { + final var foreignKeyDescriptor = getAttributeMapping().getKeyDescriptor(); + assert foreignKeyDescriptor != null; + foreignKeyDescriptor.getKeyPart().forEachSelectable( parameterList ); + for ( var columnValueParameter : parameterList ) { + final var columnReference = columnValueParameter.getColumnReference(); restrictionBindings.add( new ColumnValueBinding( columnReference, diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java index 8f8a2a2ac690..5b6715ab76b9 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java @@ -16,14 +16,7 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.FilterAliasGenerator; import org.hibernate.internal.StaticFilterAliasGenerator; -import org.hibernate.internal.util.MutableInteger; -import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.mapping.Collection; -import org.hibernate.metamodel.mapping.CollectionIdentifierDescriptor; -import org.hibernate.metamodel.mapping.CollectionPart; -import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; -import org.hibernate.metamodel.mapping.PluralAttributeMapping; -import org.hibernate.metamodel.mapping.SoftDeleteMapping; import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.persister.collection.mutation.DeleteRowsCoordinator; import org.hibernate.persister.collection.mutation.DeleteRowsCoordinatorNoOp; @@ -39,14 +32,12 @@ import org.hibernate.persister.collection.mutation.UpdateRowsCoordinator; import org.hibernate.persister.collection.mutation.UpdateRowsCoordinatorNoOp; import org.hibernate.persister.collection.mutation.UpdateRowsCoordinatorStandard; -import org.hibernate.sql.ast.SqlAstTranslator; import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.model.ast.ColumnValueBinding; import org.hibernate.sql.model.ast.ColumnValueParameterList; import org.hibernate.sql.model.ast.MutatingTableReference; import org.hibernate.sql.model.ast.RestrictedTableMutation; -import org.hibernate.sql.model.ast.TableInsert; import org.hibernate.sql.model.ast.TableMutation; import org.hibernate.sql.model.ast.builder.CollectionRowDeleteBuilder; import org.hibernate.sql.model.ast.builder.TableInsertBuilderStandard; @@ -57,6 +48,7 @@ import java.util.List; +import static org.hibernate.internal.util.collections.ArrayHelper.isAnyTrue; import static org.hibernate.internal.util.collections.CollectionHelper.arrayList; /** @@ -79,11 +71,10 @@ public class BasicCollectionPersister extends AbstractCollectionPersister { public BasicCollectionPersister( Collection collectionBinding, CollectionDataAccess cacheAccessStrategy, - RuntimeModelCreationContext creationContext) throws MappingException, CacheException { + RuntimeModelCreationContext creationContext) + throws MappingException, CacheException { super( collectionBinding, cacheAccessStrategy, creationContext ); - this.rowMutationOperations = buildRowMutationOperations(); - this.insertRowsCoordinator = buildInsertRowCoordinator(); this.updateCoordinator = buildUpdateRowCoordinator(); this.deleteRowsCoordinator = buildDeleteRowCoordinator(); @@ -138,9 +129,10 @@ protected void doProcessQueuedOps(PersistentCollection collection, Object id, private UpdateRowsCoordinator buildUpdateRowCoordinator() { - final boolean performUpdates = getCollectionSemantics().getCollectionClassification().isRowUpdatePossible() - && ArrayHelper.isAnyTrue( elementColumnIsSettable ) - && !isInverse(); + final boolean performUpdates = + getCollectionSemantics().getCollectionClassification().isRowUpdatePossible() + && isAnyTrue( elementColumnIsSettable ) + && !isInverse(); if ( !performUpdates ) { // if ( MODEL_MUTATION_LOGGER.isTraceEnabled() ) { @@ -151,8 +143,13 @@ private UpdateRowsCoordinator buildUpdateRowCoordinator() { // } return new UpdateRowsCoordinatorNoOp( this ); } - - return new UpdateRowsCoordinatorStandard( this, rowMutationOperations, getFactory() ); + else { + return new UpdateRowsCoordinatorStandard( + this, + rowMutationOperations, + getFactory() + ); + } } private InsertRowsCoordinator buildInsertRowCoordinator() { @@ -165,12 +162,17 @@ private InsertRowsCoordinator buildInsertRowCoordinator() { // } return new InsertRowsCoordinatorNoOp( this ); } - - return new InsertRowsCoordinatorStandard( this, rowMutationOperations, getFactory().getServiceRegistry() ); + else { + return new InsertRowsCoordinatorStandard( + this, + rowMutationOperations, + getFactory().getServiceRegistry() + ); + } } private DeleteRowsCoordinator buildDeleteRowCoordinator() { - if ( ! needsRemove() ) { + if ( !needsRemove() ) { // if ( MODEL_MUTATION_LOGGER.isTraceEnabled() ) { // MODEL_MUTATION_LOGGER.tracef( // "Skipping collection row deletions - %s", @@ -179,12 +181,18 @@ private DeleteRowsCoordinator buildDeleteRowCoordinator() { // } return new DeleteRowsCoordinatorNoOp( this ); } - - return new DeleteRowsCoordinatorStandard( this, rowMutationOperations, hasPhysicalIndexColumn(), getFactory().getServiceRegistry() ); + else { + return new DeleteRowsCoordinatorStandard( + this, + rowMutationOperations, + hasPhysicalIndexColumn(), + getFactory().getServiceRegistry() + ); + } } private RemoveCoordinator buildDeleteAllCoordinator() { - if ( ! needsRemove() ) { + if ( !needsRemove() ) { // if ( MODEL_MUTATION_LOGGER.isTraceEnabled() ) { // MODEL_MUTATION_LOGGER.tracef( // "Skipping collection removals - %s", @@ -193,44 +201,44 @@ private RemoveCoordinator buildDeleteAllCoordinator() { // } return new RemoveCoordinatorNoOp( this ); } - - return new RemoveCoordinatorStandard( this, this::buildDeleteAllOperation, getFactory().getServiceRegistry() ); + else { + return new RemoveCoordinatorStandard( + this, + this::buildDeleteAllOperation, + getFactory().getServiceRegistry() + ); + } } @Override public RestrictedTableMutation generateDeleteAllAst(MutatingTableReference tableReference) { - assert getAttributeMapping() != null; - - final SoftDeleteMapping softDeleteMapping = getAttributeMapping().getSoftDeleteMapping(); + final var attributeMapping = getAttributeMapping(); + assert attributeMapping != null; + final var softDeleteMapping = attributeMapping.getSoftDeleteMapping(); if ( softDeleteMapping == null ) { return super.generateDeleteAllAst( tableReference ); } - - final ForeignKeyDescriptor fkDescriptor = getAttributeMapping().getKeyDescriptor(); - assert fkDescriptor != null; - - final int keyColumnCount = fkDescriptor.getJdbcTypeCount(); - final ColumnValueParameterList parameterBinders = new ColumnValueParameterList( - tableReference, - ParameterUsage.RESTRICT, - keyColumnCount - ); - final java.util.List restrictionBindings = arrayList( keyColumnCount ); - applyKeyRestrictions( tableReference, parameterBinders, restrictionBindings ); - - final ColumnReference softDeleteColumn = new ColumnReference( tableReference, softDeleteMapping ); - final ColumnValueBinding nonDeletedBinding = softDeleteMapping.createNonDeletedValueBinding( softDeleteColumn ); - final ColumnValueBinding deletedBinding = softDeleteMapping.createDeletedValueBinding( softDeleteColumn ); - - return new TableUpdateStandard( - tableReference, - this, - "soft-delete removal", - List.of( deletedBinding ), - restrictionBindings, - List.of( nonDeletedBinding ) - ); + else { + final var foreignKeyDescriptor = attributeMapping.getKeyDescriptor(); + assert foreignKeyDescriptor != null; + final int keyColumnCount = foreignKeyDescriptor.getJdbcTypeCount(); + final var parameterBinders = + new ColumnValueParameterList( tableReference, ParameterUsage.RESTRICT, keyColumnCount ); + final List restrictionBindings = arrayList( keyColumnCount ); + applyKeyRestrictions( parameterBinders, restrictionBindings ); + final var softDeleteColumn = new ColumnReference( tableReference, softDeleteMapping ); + final var nonDeletedBinding = softDeleteMapping.createNonDeletedValueBinding( softDeleteColumn ); + final var deletedBinding = softDeleteMapping.createDeletedValueBinding( softDeleteColumn ); + return new TableUpdateStandard( + tableReference, + this, + "soft-delete removal", + List.of( deletedBinding ), + restrictionBindings, + List.of( nonDeletedBinding ) + ); + } } protected RowMutationOperations buildRowMutationOperations() { @@ -249,7 +257,7 @@ protected RowMutationOperations buildRowMutationOperations() { final RowMutationOperations.Values updateRowValues; final RowMutationOperations.Restrictions updateRowRestrictions; if ( getCollectionSemantics().getCollectionClassification().isRowUpdatePossible() - && ArrayHelper.isAnyTrue( elementColumnIsSettable ) + && isAnyTrue( elementColumnIsSettable ) && !isInverse() ) { updateRowOperationProducer = this::generateUpdateRowOperation; updateRowValues = this::applyUpdateRowValues; @@ -291,67 +299,51 @@ protected RowMutationOperations buildRowMutationOperations() { // Insert handling private JdbcMutationOperation generateInsertRowOperation(MutatingTableReference tableReference) { - if ( getIdentifierTableMapping().getInsertDetails().getCustomSql() != null ) { - return buildCustomSqlInsertRowOperation( tableReference ); - } - - return buildGeneratedInsertRowOperation( tableReference ); + return getIdentifierTableMapping().getInsertDetails().getCustomSql() != null + ? buildCustomSqlInsertRowOperation( tableReference ) + : buildGeneratedInsertRowOperation( tableReference ); } private JdbcMutationOperation buildCustomSqlInsertRowOperation(MutatingTableReference tableReference) { - final TableInsertBuilderStandard insertBuilder = new TableInsertBuilderStandard( this, tableReference, getFactory() ); + final var factory = getFactory(); + final var insertBuilder = new TableInsertBuilderStandard( this, tableReference, factory ); applyInsertDetails( insertBuilder ); - - final TableInsert tableInsert = insertBuilder.buildMutation(); - return tableInsert.createMutationOperation( null, getFactory() ); + return insertBuilder.buildMutation().createMutationOperation( null, factory ); } private void applyInsertDetails(TableInsertBuilderStandard insertBuilder) { - final PluralAttributeMapping attributeMapping = getAttributeMapping(); - - final ForeignKeyDescriptor foreignKey = attributeMapping.getKeyDescriptor(); - foreignKey.getKeyPart().forEachSelectable( insertBuilder ); - - final CollectionIdentifierDescriptor identifierDescriptor = attributeMapping.getIdentifierDescriptor(); - final CollectionPart indexDescriptor = attributeMapping.getIndexDescriptor(); + final var attributeMapping = getAttributeMapping(); + attributeMapping.getKeyDescriptor().getKeyPart().forEachSelectable( insertBuilder ); + final var identifierDescriptor = attributeMapping.getIdentifierDescriptor(); + final var indexDescriptor = attributeMapping.getIndexDescriptor(); if ( identifierDescriptor != null ) { identifierDescriptor.forEachSelectable( insertBuilder ); } else if ( indexDescriptor != null ) { indexDescriptor.forEachInsertable( insertBuilder ); } - attributeMapping.getElementDescriptor().forEachInsertable( insertBuilder ); - - final SoftDeleteMapping softDeleteMapping = getAttributeMapping().getSoftDeleteMapping(); + final var softDeleteMapping = attributeMapping.getSoftDeleteMapping(); if ( softDeleteMapping != null ) { - final ColumnReference columnReference = new ColumnReference( insertBuilder.getMutatingTable(), softDeleteMapping ); + final var columnReference = new ColumnReference( insertBuilder.getMutatingTable(), softDeleteMapping ); insertBuilder.addValueColumn( softDeleteMapping.createNonDeletedValueBinding( columnReference ) ); } } private JdbcMutationOperation buildGeneratedInsertRowOperation(MutatingTableReference tableReference) { - final TableMutation sqlAst = generateInsertRowAst( tableReference ); - - final SqlAstTranslator translator = getFactory().getJdbcServices() - .getDialect() - .getSqlAstTranslatorFactory() - .buildModelMutationTranslator( sqlAst, getFactory() ); - - return translator.translate( null, MutationQueryOptions.INSTANCE ); + return getSqlAstTranslatorFactory() + .buildModelMutationTranslator( generateInsertRowAst( tableReference ), getFactory() ) + .translate( null, MutationQueryOptions.INSTANCE ); } private TableMutation generateInsertRowAst(MutatingTableReference tableReference) { - final PluralAttributeMapping pluralAttribute = getAttributeMapping(); + final var pluralAttribute = getAttributeMapping(); assert pluralAttribute != null; - - final ForeignKeyDescriptor fkDescriptor = pluralAttribute.getKeyDescriptor(); - assert fkDescriptor != null; - - final TableInsertBuilderStandard insertBuilder = new TableInsertBuilderStandard( this, tableReference, getFactory() ); + final var foreignKeyDescriptor = pluralAttribute.getKeyDescriptor(); + assert foreignKeyDescriptor != null; + final var insertBuilder = new TableInsertBuilderStandard( this, tableReference, getFactory() ); applyInsertDetails( insertBuilder ); - //noinspection unchecked,rawtypes return (TableMutation) insertBuilder.buildMutation(); } @@ -363,14 +355,12 @@ private void applyInsertRowValues( int rowPosition, SharedSessionContractImplementor session, JdbcValueBindings jdbcValueBindings) { - final PluralAttributeMapping attributeMapping = getAttributeMapping(); - if ( key == null ) { throw new IllegalArgumentException( "null key for collection: " + getNavigableRole().getFullPath() ); } - - final ForeignKeyDescriptor foreignKey = attributeMapping.getKeyDescriptor(); - foreignKey.getKeyPart().decompose( + final var attributeMapping = getAttributeMapping(); + final var foreignKeyDescriptor = attributeMapping.getKeyDescriptor(); + foreignKeyDescriptor.getKeyPart().decompose( key, 0, jdbcValueBindings, @@ -379,10 +369,8 @@ private void applyInsertRowValues( session ); - final MutableInteger columnPositionCount = new MutableInteger(); - if ( attributeMapping.getIdentifierDescriptor() != null ) { - getAttributeMapping().getIdentifierDescriptor().decompose( + attributeMapping.getIdentifierDescriptor().decompose( collection.getIdentifier( rowValue, rowPosition ), 0, jdbcValueBindings, @@ -399,26 +387,22 @@ else if ( attributeMapping.getIndexDescriptor() != null ) { // 1) not the managed-type structure from ModelPart // 2) not BasicType from ValueMapping // essentially any basic or composite mapping of column(s) - - getAttributeMapping().getIndexDescriptor().decompose( + attributeMapping.getIndexDescriptor().decompose( incrementIndexByBase( collection.getIndex( rowValue, rowPosition, this ) ), 0, indexColumnIsSettable, jdbcValueBindings, (valueIndex, settable, bindings, jdbcValue, jdbcValueMapping) -> { - if ( !jdbcValueMapping.getContainingTableExpression().equals( getTableName() ) ) { - // indicates a many-to-many mapping and the index is contained on the - // associated entity table - we skip it here - return; - } - if ( settable[valueIndex] ) { - bindings.bindValue( jdbcValue, jdbcValueMapping, ParameterUsage.SET ); + if ( jdbcValueMapping.getContainingTableExpression().equals( getTableName() ) ) { + if ( settable[valueIndex] ) { + bindings.bindValue( jdbcValue, jdbcValueMapping, ParameterUsage.SET ); + } } + // otherwise a many-to-many mapping and the index is defined + // on the associated entity table - we skip it here }, session ); - - columnPositionCount.set( 0 ); } attributeMapping.getElementDescriptor().decompose( @@ -440,22 +424,17 @@ else if ( attributeMapping.getIndexDescriptor() != null ) { // Update handling private JdbcMutationOperation generateUpdateRowOperation(MutatingTableReference tableReference) { - final RestrictedTableMutation sqlAst = generateUpdateRowAst( tableReference ); - - final SqlAstTranslator translator = getFactory().getJdbcServices() - .getDialect() - .getSqlAstTranslatorFactory() - .buildModelMutationTranslator( sqlAst, getFactory() ); - - return translator.translate( null, MutationQueryOptions.INSTANCE ); + return getSqlAstTranslatorFactory() + .buildModelMutationTranslator( generateUpdateRowAst( tableReference ), getFactory() ) + .translate( null, MutationQueryOptions.INSTANCE ); } private RestrictedTableMutation generateUpdateRowAst(MutatingTableReference tableReference) { - final PluralAttributeMapping attribute = getAttributeMapping(); + final var attribute = getAttributeMapping(); assert attribute != null; - // note that custom sql update row details are handled by TableUpdateBuilderStandard - final TableUpdateBuilderStandard updateBuilder = new TableUpdateBuilderStandard<>( + // note that custom SQL update row details are handled by TableUpdateBuilderStandard + final var updateBuilder = new TableUpdateBuilderStandard<>( this, tableReference, getFactory(), @@ -475,7 +454,6 @@ private RestrictedTableMutation generateUpdateRowAst(Muta } else { updateBuilder.addKeyRestrictionsLeniently( attribute.getKeyDescriptor().getKeyPart() ); - if ( attribute.getIndexDescriptor() != null && !indexContainsFormula ) { updateBuilder.addKeyRestrictionsLeniently( attribute.getIndexDescriptor() ); } @@ -495,22 +473,15 @@ private void applyUpdateRowValues( int entryPosition, SharedSessionContractImplementor session, JdbcValueBindings jdbcValueBindings) { - final Object element = collection.getElement( entry ); - final CollectionPart elementDescriptor = getAttributeMapping().getElementDescriptor(); - elementDescriptor.decompose( - element, + getAttributeMapping().getElementDescriptor().decompose( + collection.getElement( entry ), 0, jdbcValueBindings, null, (valueIndex, bindings, y, jdbcValue, jdbcValueMapping) -> { - if ( !jdbcValueMapping.isUpdateable() || jdbcValueMapping.isFormula() ) { - return; + if ( jdbcValueMapping.isUpdateable() && !jdbcValueMapping.isFormula() ) { + bindings.bindValue( jdbcValue, jdbcValueMapping, ParameterUsage.SET ); } - bindings.bindValue( - jdbcValue, - jdbcValueMapping, - ParameterUsage.SET - ); }, session ); @@ -523,11 +494,10 @@ private void applyUpdateRowRestrictions( int entryPosition, SharedSessionContractImplementor session, JdbcValueBindings jdbcValueBindings) { - if ( getAttributeMapping().getIdentifierDescriptor() != null ) { - final CollectionIdentifierDescriptor identifierDescriptor = getAttributeMapping().getIdentifierDescriptor(); - final Object identifier = collection.getIdentifier( entry, entryPosition ); - identifierDescriptor.decompose( - identifier, + final var attributeMapping = getAttributeMapping(); + if ( attributeMapping.getIdentifierDescriptor() != null ) { + attributeMapping.getIdentifierDescriptor().decompose( + collection.getIdentifier( entry, entryPosition ), 0, jdbcValueBindings, null, @@ -536,7 +506,7 @@ private void applyUpdateRowRestrictions( ); } else { - getAttributeMapping().getKeyDescriptor().getKeyPart().decompose( + attributeMapping.getKeyDescriptor().getKeyPart().decompose( key, 0, jdbcValueBindings, @@ -545,10 +515,12 @@ private void applyUpdateRowRestrictions( session ); - if ( getAttributeMapping().getIndexDescriptor() != null && !indexContainsFormula ) { - final Object index = collection.getIndex( entry, entryPosition, getAttributeMapping().getCollectionDescriptor() ); + if ( attributeMapping.getIndexDescriptor() != null && !indexContainsFormula ) { + final Object index = + collection.getIndex( entry, entryPosition, + attributeMapping.getCollectionDescriptor() ); final Object adjustedIndex = incrementIndexByBase( index ); - getAttributeMapping().getIndexDescriptor().decompose( + attributeMapping.getIndexDescriptor().decompose( adjustedIndex, 0, jdbcValueBindings, @@ -558,17 +530,15 @@ private void applyUpdateRowRestrictions( ); } else { - final Object snapshotElement = collection.getSnapshotElement( entry, entryPosition ); - getAttributeMapping().getElementDescriptor().decompose( - snapshotElement, + attributeMapping.getElementDescriptor().decompose( + collection.getSnapshotElement( entry, entryPosition ), 0, jdbcValueBindings, null, (valueIndex, bindings, noop, jdbcValue, jdbcValueMapping) -> { - if ( jdbcValueMapping.isNullable() || jdbcValueMapping.isFormula() ) { - return; + if ( !jdbcValueMapping.isNullable() && !jdbcValueMapping.isFormula() ) { + bindings.bindValue( jdbcValue, jdbcValueMapping, ParameterUsage.RESTRICT ); } - bindings.bindValue( jdbcValue, jdbcValueMapping, ParameterUsage.RESTRICT ); }, session ); @@ -581,90 +551,77 @@ private void applyUpdateRowRestrictions( // Delete handling private JdbcMutationOperation generateDeleteRowOperation(MutatingTableReference tableReference) { - final RestrictedTableMutation sqlAst = generateDeleteRowAst( tableReference ); - - final SqlAstTranslator translator = getFactory().getJdbcServices() - .getDialect() - .getSqlAstTranslatorFactory() - .buildModelMutationTranslator( sqlAst, getFactory() ); - - return translator.translate( null, MutationQueryOptions.INSTANCE ); + return getSqlAstTranslatorFactory() + .buildModelMutationTranslator( generateDeleteRowAst( tableReference ), getFactory() ) + .translate( null, MutationQueryOptions.INSTANCE ); } private RestrictedTableMutation generateDeleteRowAst(MutatingTableReference tableReference) { - final PluralAttributeMapping pluralAttribute = getAttributeMapping(); + final var pluralAttribute = getAttributeMapping(); assert pluralAttribute != null; - - final SoftDeleteMapping softDeleteMapping = pluralAttribute.getSoftDeleteMapping(); + final var softDeleteMapping = pluralAttribute.getSoftDeleteMapping(); if ( softDeleteMapping != null ) { return generateSoftDeleteRowsAst( tableReference ); } - - final ForeignKeyDescriptor fkDescriptor = pluralAttribute.getKeyDescriptor(); - assert fkDescriptor != null; - - // note that custom sql delete row details are handled by CollectionRowDeleteBuilder - final CollectionRowDeleteBuilder deleteBuilder = new CollectionRowDeleteBuilder( - this, - tableReference, - getFactory(), - sqlWhereString - ); - - if ( pluralAttribute.getIdentifierDescriptor() != null ) { - deleteBuilder.addKeyRestrictionsLeniently( pluralAttribute.getIdentifierDescriptor() ); - } else { - deleteBuilder.addKeyRestrictionsLeniently( pluralAttribute.getKeyDescriptor().getKeyPart() ); - - if ( hasIndex() && !indexContainsFormula ) { - assert pluralAttribute.getIndexDescriptor() != null; - deleteBuilder.addKeyRestrictionsLeniently( pluralAttribute.getIndexDescriptor() ); + final var foreignKeyDescriptor = pluralAttribute.getKeyDescriptor(); + assert foreignKeyDescriptor != null; + // note that custom sql delete row details are handled by CollectionRowDeleteBuilder + final var deleteBuilder = new CollectionRowDeleteBuilder( + this, + tableReference, + getFactory(), + sqlWhereString + ); + if ( pluralAttribute.getIdentifierDescriptor() != null ) { + deleteBuilder.addKeyRestrictionsLeniently( pluralAttribute.getIdentifierDescriptor() ); } else { - deleteBuilder.addKeyRestrictions( pluralAttribute.getElementDescriptor() ); + deleteBuilder.addKeyRestrictionsLeniently( foreignKeyDescriptor.getKeyPart() ); + if ( hasIndex() && !indexContainsFormula ) { + assert pluralAttribute.getIndexDescriptor() != null; + deleteBuilder.addKeyRestrictionsLeniently( pluralAttribute.getIndexDescriptor() ); + } + else { + deleteBuilder.addKeyRestrictions( pluralAttribute.getElementDescriptor() ); + } } + //noinspection unchecked,rawtypes + return (RestrictedTableMutation) deleteBuilder.buildMutation(); } - - //noinspection unchecked,rawtypes - return (RestrictedTableMutation) deleteBuilder.buildMutation(); } protected RestrictedTableMutation generateSoftDeleteRowsAst(MutatingTableReference tableReference) { - final SoftDeleteMapping softDeleteMapping = getAttributeMapping().getSoftDeleteMapping(); + final var attributeMapping = getAttributeMapping(); + final var softDeleteMapping = attributeMapping.getSoftDeleteMapping(); assert softDeleteMapping != null; - - final ForeignKeyDescriptor fkDescriptor = getAttributeMapping().getKeyDescriptor(); - assert fkDescriptor != null; - + final var foreignKeyDescriptor = attributeMapping.getKeyDescriptor(); + assert foreignKeyDescriptor != null; final TableUpdateBuilderStandard updateBuilder = new TableUpdateBuilderStandard<>( this, tableReference, getFactory(), sqlWhereString ); - - if ( getAttributeMapping().getIdentifierDescriptor() != null ) { - updateBuilder.addKeyRestrictionsLeniently( getAttributeMapping().getIdentifierDescriptor() ); + if ( attributeMapping.getIdentifierDescriptor() != null ) { + updateBuilder.addKeyRestrictionsLeniently( attributeMapping.getIdentifierDescriptor() ); } else { - updateBuilder.addKeyRestrictionsLeniently( getAttributeMapping().getKeyDescriptor().getKeyPart() ); - + updateBuilder.addKeyRestrictionsLeniently( foreignKeyDescriptor.getKeyPart() ); if ( hasIndex() && !indexContainsFormula ) { - assert getAttributeMapping().getIndexDescriptor() != null; - updateBuilder.addKeyRestrictionsLeniently( getAttributeMapping().getIndexDescriptor() ); + assert attributeMapping.getIndexDescriptor() != null; + updateBuilder.addKeyRestrictionsLeniently( attributeMapping.getIndexDescriptor() ); } else { - updateBuilder.addKeyRestrictions( getAttributeMapping().getElementDescriptor() ); + updateBuilder.addKeyRestrictions( attributeMapping.getElementDescriptor() ); } } - final ColumnReference softDeleteColumnReference = new ColumnReference( tableReference, softDeleteMapping ); + final var softDeleteColumnReference = new ColumnReference( tableReference, softDeleteMapping ); // apply the assignment updateBuilder.addValueColumn( softDeleteMapping.createDeletedValueBinding( softDeleteColumnReference ) ); // apply the restriction updateBuilder.addNonKeyRestriction( softDeleteMapping.createNonDeletedValueBinding( softDeleteColumnReference ) ); - return updateBuilder.buildMutation(); } @@ -675,8 +632,7 @@ private void applyDeleteRowRestrictions( int rowPosition, SharedSessionContractImplementor session, JdbcValueBindings jdbcValueBindings) { - final PluralAttributeMapping attributeMapping = getAttributeMapping(); - + final var attributeMapping = getAttributeMapping(); if ( attributeMapping.getIdentifierDescriptor() != null ) { attributeMapping.getIdentifierDescriptor().decompose( rowValue, @@ -688,7 +644,7 @@ private void applyDeleteRowRestrictions( ); } else { - getAttributeMapping().getKeyDescriptor().getKeyPart().decompose( + attributeMapping.getKeyDescriptor().getKeyPart().decompose( keyValue, 0, jdbcValueBindings, @@ -696,7 +652,6 @@ private void applyDeleteRowRestrictions( RowMutationOperations.DEFAULT_RESTRICTOR, session ); - if ( hasPhysicalIndexColumn() ) { attributeMapping.getIndexDescriptor().decompose( incrementIndexByBase( rowValue ), @@ -714,10 +669,9 @@ private void applyDeleteRowRestrictions( jdbcValueBindings, null, (valueIndex, bindings, noop, jdbcValue, jdbcValueMapping) -> { - if ( jdbcValueMapping.isNullable() || jdbcValueMapping.isFormula() ) { - return; + if ( !jdbcValueMapping.isNullable() && !jdbcValueMapping.isFormula() ) { + bindings.bindValue( jdbcValue, jdbcValueMapping, ParameterUsage.RESTRICT ); } - bindings.bindValue( jdbcValue, jdbcValueMapping, ParameterUsage.RESTRICT ); }, session ); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java index 87210cbb1c6c..bcf5d2c82439 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java @@ -16,7 +16,6 @@ import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey; import org.hibernate.engine.jdbc.mutation.JdbcValueBindings; -import org.hibernate.engine.jdbc.mutation.MutationExecutor; import org.hibernate.engine.jdbc.mutation.ParameterUsage; import org.hibernate.engine.jdbc.mutation.internal.MutationQueryOptions; import org.hibernate.engine.jdbc.mutation.spi.MutationExecutorService; @@ -24,11 +23,6 @@ import org.hibernate.internal.FilterAliasGenerator; import org.hibernate.jdbc.Expectation; import org.hibernate.mapping.Collection; -import org.hibernate.metamodel.mapping.CollectionPart; -import org.hibernate.metamodel.mapping.EntityIdentifierMapping; -import org.hibernate.metamodel.mapping.EntityMappingType; -import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; -import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.metamodel.mapping.internal.EntityCollectionPart; import org.hibernate.metamodel.mapping.internal.OneToManyCollectionPart; @@ -51,17 +45,13 @@ import org.hibernate.persister.collection.mutation.UpdateRowsCoordinatorNoOp; import org.hibernate.persister.collection.mutation.UpdateRowsCoordinatorOneToMany; import org.hibernate.persister.collection.mutation.UpdateRowsCoordinatorTablePerSubclass; -import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.UnionSubclassEntityPersister; -import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.sql.ast.spi.SqlAstCreationState; import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.predicate.Predicate; -import org.hibernate.sql.model.MutationOperation; import org.hibernate.sql.model.MutationType; import org.hibernate.sql.model.ast.ColumnValueBinding; -import org.hibernate.sql.model.ast.ColumnValueParameter; import org.hibernate.sql.model.ast.ColumnValueParameterList; import org.hibernate.sql.model.ast.ColumnWriteFragment; import org.hibernate.sql.model.ast.MutatingTableReference; @@ -104,15 +94,17 @@ public class OneToManyPersister extends AbstractCollectionPersister { public OneToManyPersister( Collection collectionBinding, CollectionDataAccess cacheAccessStrategy, - RuntimeModelCreationContext creationContext) throws MappingException, CacheException { + RuntimeModelCreationContext creationContext) + throws MappingException, CacheException { super( collectionBinding, cacheAccessStrategy, creationContext ); keyIsNullable = collectionBinding.getKey().isNullable(); - doWriteEvenWhenInverse = isInverse - && hasIndex() - && !indexContainsFormula - && isAnyTrue( indexColumnIsSettable ) - && !getElementPersisterInternal().managesColumns( indexColumnNames ); + doWriteEvenWhenInverse = + isInverse + && hasIndex() + && !indexContainsFormula + && isAnyTrue( indexColumnIsSettable ) + && !getElementPersisterInternal().managesColumns( indexColumnNames ); rowMutationOperations = buildRowMutationOperations(); @@ -120,7 +112,7 @@ && isAnyTrue( indexColumnIsSettable ) updateRowsCoordinator = buildUpdateCoordinator(); deleteRowsCoordinator = buildDeleteCoordinator(); removeCoordinator = buildDeleteAllCoordinator(); - mutationExecutorService = creationContext.getServiceRegistry().getService( MutationExecutorService.class ); + mutationExecutorService = creationContext.getServiceRegistry().getService( MutationExecutorService.class ); } @Override @@ -198,18 +190,18 @@ private void writeIndex( // users complain. if ( doWriteEvenWhenInverse && entries.hasNext() ) { - final JdbcMutationOperation updateRowOperation = rowMutationOperations.getUpdateRowOperation(); - final RowMutationOperations.Values updateRowValues = rowMutationOperations.getUpdateRowValues(); - final RowMutationOperations.Restrictions updateRowRestrictions = rowMutationOperations.getUpdateRowRestrictions(); + final var updateRowOperation = rowMutationOperations.getUpdateRowOperation(); + final var updateRowValues = rowMutationOperations.getUpdateRowValues(); + final var updateRowRestrictions = rowMutationOperations.getUpdateRowRestrictions(); assert areAllNonNull( updateRowOperation, updateRowValues, updateRowRestrictions ); - final MutationExecutor mutationExecutor = mutationExecutorService.createExecutor( + final var mutationExecutor = mutationExecutorService.createExecutor( () -> new BasicBatchKey( getNavigableRole() + "#INDEX" ), MutationOperationGroupFactory.singleOperation( MutationType.UPDATE, this, updateRowOperation ), session ); - final JdbcValueBindings jdbcValueBindings = mutationExecutor.getJdbcValueBindings(); + final var jdbcValueBindings = mutationExecutor.getJdbcValueBindings(); try { int nextIndex = ( resetIndex ? 0 : getSize( key, session ) ) + Math.max( getAttributeMapping().getIndexMetadata().getListIndexBase(), 0 ); @@ -264,7 +256,6 @@ protected void applyWhereFragments( TableGroup tableGroup, SqlAstCreationState astCreationState) { super.applyWhereFragments( predicateConsumer, alias, tableGroup, astCreationState ); - if ( !astCreationState.supportsEntityNameUsage() ) { // We only need to apply discriminator for loads, since queries with joined // inheritance subtypes are already filtered by the entity name usage logic @@ -290,26 +281,24 @@ public FilterAliasGenerator getFilterAliasGenerator(TableGroup rootTableGroup) { @Override public RestrictedTableMutation generateDeleteAllAst(MutatingTableReference tableReference) { - assert getAttributeMapping() != null; + final var attributeMapping = getAttributeMapping(); + assert attributeMapping != null; - final ForeignKeyDescriptor fkDescriptor = getAttributeMapping().getKeyDescriptor(); - assert fkDescriptor != null; + final var foreignKeyDescriptor = attributeMapping.getKeyDescriptor(); + assert foreignKeyDescriptor != null; - final int keyColumnCount = fkDescriptor.getJdbcTypeCount(); + final int keyColumnCount = foreignKeyDescriptor.getJdbcTypeCount(); final int valuesCount = hasIndex() ? keyColumnCount + indexColumnNames.length : keyColumnCount; - final ColumnValueParameterList parameterBinders = new ColumnValueParameterList( - tableReference, - ParameterUsage.RESTRICT, - keyColumnCount - ); + final var parameterBinders = + new ColumnValueParameterList( tableReference, ParameterUsage.RESTRICT, keyColumnCount ); final List keyRestrictionBindings = arrayList( keyColumnCount ); final List valueBindings = arrayList( valuesCount ); - fkDescriptor.getKeyPart().forEachSelectable( parameterBinders ); - for ( ColumnValueParameter columnValueParameter : parameterBinders ) { - final ColumnReference columnReference = columnValueParameter.getColumnReference(); + foreignKeyDescriptor.getKeyPart().forEachSelectable( parameterBinders ); + for ( var columnValueParameter : parameterBinders ) { + final var columnReference = columnValueParameter.getColumnReference(); keyRestrictionBindings.add( new ColumnValueBinding( columnReference, @@ -329,14 +318,15 @@ public RestrictedTableMutation generateDeleteAllAst(Mutat } if ( hasIndex() && !indexContainsFormula ) { - getAttributeMapping().getIndexDescriptor().forEachSelectable( (selectionIndex, selectableMapping) -> { - if ( ! selectableMapping.isUpdateable() ) { - return; + attributeMapping.getIndexDescriptor().forEachSelectable( (selectionIndex, selectableMapping) -> { + if ( selectableMapping.isUpdateable() ) { + valueBindings.add( + new ColumnValueBinding( + new ColumnReference( tableReference, selectableMapping ), + new ColumnWriteFragment( "null", selectableMapping.getJdbcMapping() ) + ) + ); } - valueBindings.add( - new ColumnValueBinding( new ColumnReference( tableReference, selectableMapping ), - new ColumnWriteFragment( "null", selectableMapping.getJdbcMapping() ) - ) ); } ); } @@ -403,7 +393,6 @@ private RowMutationOperations buildRowMutationOperations() { ); } - private InsertRowsCoordinator buildInsertCoordinator() { if ( isInverse() || !isRowInsertEnabled() ) { // if ( MODEL_MUTATION_LOGGER.isTraceEnabled() ) { @@ -412,8 +401,8 @@ private InsertRowsCoordinator buildInsertCoordinator() { return new InsertRowsCoordinatorNoOp( this ); } else { - final ServiceRegistryImplementor serviceRegistry = getFactory().getServiceRegistry(); - final EntityPersister elementPersister = getElementPersisterInternal(); + final var serviceRegistry = getFactory().getServiceRegistry(); + final var elementPersister = getElementPersisterInternal(); return elementPersister != null && elementPersister.hasSubclasses() && elementPersister instanceof UnionSubclassEntityPersister ? new InsertRowsCoordinatorTablePerSubclass( this, rowMutationOperations, serviceRegistry ) @@ -429,11 +418,12 @@ private UpdateRowsCoordinator buildUpdateCoordinator() { return new UpdateRowsCoordinatorNoOp( this ); } else { - final EntityPersister elementPersister = getElementPersisterInternal(); + final var elementPersister = getElementPersisterInternal(); + final var factory = getFactory(); return elementPersister != null && elementPersister.hasSubclasses() - && elementPersister instanceof UnionSubclassEntityPersister - ? new UpdateRowsCoordinatorTablePerSubclass( this, rowMutationOperations, getFactory() ) - : new UpdateRowsCoordinatorOneToMany( this, rowMutationOperations, getFactory() ); + && elementPersister instanceof UnionSubclassEntityPersister + ? new UpdateRowsCoordinatorTablePerSubclass( this, rowMutationOperations, factory ) + : new UpdateRowsCoordinatorOneToMany( this, rowMutationOperations, factory ); } } @@ -445,10 +435,10 @@ private DeleteRowsCoordinator buildDeleteCoordinator() { return new DeleteRowsCoordinatorNoOp( this ); } else { - final EntityPersister elementPersister = getElementPersisterInternal(); - final ServiceRegistryImplementor serviceRegistry = getFactory().getServiceRegistry(); + final var elementPersister = getElementPersisterInternal(); + final var serviceRegistry = getFactory().getServiceRegistry(); return elementPersister != null && elementPersister.hasSubclasses() - && elementPersister instanceof UnionSubclassEntityPersister + && elementPersister instanceof UnionSubclassEntityPersister // never delete by index for one-to-many ? new DeleteRowsCoordinatorTablePerSubclass( this, rowMutationOperations, false, serviceRegistry ) : new DeleteRowsCoordinatorStandard( this, rowMutationOperations, false, serviceRegistry ); @@ -463,33 +453,33 @@ private RemoveCoordinator buildDeleteAllCoordinator() { return new RemoveCoordinatorNoOp( this ); } else { - final ServiceRegistryImplementor serviceRegistry = getFactory().getServiceRegistry(); - final EntityPersister elementPersister = getElementPersisterInternal(); + final var serviceRegistry = getFactory().getServiceRegistry(); + final var elementPersister = getElementPersisterInternal(); return elementPersister != null && elementPersister.hasSubclasses() - && elementPersister instanceof UnionSubclassEntityPersister + && elementPersister instanceof UnionSubclassEntityPersister ? new RemoveCoordinatorTablePerSubclass( this, this::buildDeleteAllOperation, serviceRegistry ) : new RemoveCoordinatorStandard( this, this::buildDeleteAllOperation, serviceRegistry ); } } private JdbcMutationOperation generateDeleteRowOperation(MutatingTableReference tableReference) { - return getFactory().getJdbcServices().getDialect().getSqlAstTranslatorFactory() + return getSqlAstTranslatorFactory() .buildModelMutationTranslator( generateDeleteRowAst( tableReference ), getFactory() ) .translate( null, MutationQueryOptions.INSTANCE ); } public RestrictedTableMutation generateDeleteRowAst(MutatingTableReference tableReference) { - // note that custom sql delete row details are handled by CollectionRowUpdateBuilder - final CollectionRowDeleteByUpdateSetNullBuilder updateBuilder = + // note that custom SQL delete row details are handled by CollectionRowUpdateBuilder + final var updateBuilder = new CollectionRowDeleteByUpdateSetNullBuilder<>( this, tableReference, getFactory(), sqlWhereString ); // for each key column - // 1) set the value to null // 2) restrict based on key value - final ForeignKeyDescriptor keyDescriptor = getAttributeMapping().getKeyDescriptor(); - final int keyTypeCount = keyDescriptor.getJdbcTypeCount(); + final var foreignKeyDescriptor = getAttributeMapping().getKeyDescriptor(); + final int keyTypeCount = foreignKeyDescriptor.getJdbcTypeCount(); for ( int i = 0; i < keyTypeCount; i++ ) { - final SelectableMapping selectable = keyDescriptor.getSelectable( i ); + final SelectableMapping selectable = foreignKeyDescriptor.getSelectable( i ); if ( !selectable.isFormula() ) { if ( selectable.isUpdateable() ) { // set null @@ -507,11 +497,11 @@ public RestrictedTableMutation generateDeleteRowAst(Mutat // set the value for each index column to null if ( hasIndex() && !indexContainsFormula ) { - final CollectionPart indexDescriptor = getAttributeMapping().getIndexDescriptor(); + final var indexDescriptor = getAttributeMapping().getIndexDescriptor(); assert indexDescriptor != null; final int indexTypeCount = indexDescriptor.getJdbcTypeCount(); for ( int i = 0; i < indexTypeCount; i++ ) { - final SelectableMapping selectable = indexDescriptor.getSelectable( i ); + final var selectable = indexDescriptor.getSelectable( i ); if ( selectable.isUpdateable() ) { updateBuilder.addValueColumn( selectable.getSelectionExpression(), @@ -525,8 +515,8 @@ public RestrictedTableMutation generateDeleteRowAst(Mutat // for one-to-many, we know the element is an entity and need to restrict the update // based on the element's id - final EntityCollectionPart entityPart = (EntityCollectionPart) getAttributeMapping().getElementDescriptor(); - final EntityIdentifierMapping entityId = entityPart.getAssociatedEntityMappingType().getIdentifierMapping(); + final var entityPart = (EntityCollectionPart) getAttributeMapping().getElementDescriptor(); + final var entityId = entityPart.getAssociatedEntityMappingType().getIdentifierMapping(); updateBuilder.addKeyRestrictionsLeniently( entityId ); //noinspection unchecked,rawtypes @@ -540,7 +530,7 @@ private void applyDeleteRowRestrictions( int rowPosition, SharedSessionContractImplementor session, JdbcValueBindings jdbcValueBindings) { - final PluralAttributeMapping pluralAttribute = getAttributeMapping(); + final var pluralAttribute = getAttributeMapping(); pluralAttribute.getKeyDescriptor().decompose( keyValue, 0, @@ -561,25 +551,22 @@ private void applyDeleteRowRestrictions( private JdbcMutationOperation generateInsertRowOperation(MutatingTableReference tableReference) { - // NOTE : `TableUpdateBuilderStandard` and `TableUpdate` already handle custom-sql - final TableUpdate tableUpdate = buildTableUpdate( tableReference ); - return tableUpdate.createMutationOperation( null, getFactory() ); + // NOTE: `TableUpdateBuilderStandard` and `TableUpdate` already handle custom-sql + return buildTableUpdate( tableReference ) + .createMutationOperation( null, getFactory() ); } private TableUpdate buildTableUpdate(MutatingTableReference tableReference) { final TableUpdateBuilderStandard updateBuilder = new TableUpdateBuilderStandard<>( this, tableReference, getFactory(), sqlWhereString ); - - final PluralAttributeMapping attributeMapping = getAttributeMapping(); + final var attributeMapping = getAttributeMapping(); attributeMapping.getKeyDescriptor().getKeyPart().forEachSelectable( updateBuilder ); - - final CollectionPart indexDescriptor = attributeMapping.getIndexDescriptor(); + final var indexDescriptor = attributeMapping.getIndexDescriptor(); if ( indexDescriptor != null ) { indexDescriptor.forEachUpdatable( updateBuilder ); } - - final EntityCollectionPart elementDescriptor = (EntityCollectionPart) attributeMapping.getElementDescriptor(); - final EntityMappingType elementType = elementDescriptor.getAssociatedEntityMappingType(); + final var elementDescriptor = (EntityCollectionPart) attributeMapping.getElementDescriptor(); + final var elementType = elementDescriptor.getAssociatedEntityMappingType(); assert elementType.containsTableReference( tableReference.getTableName() ); updateBuilder.addKeyRestrictionsLeniently( elementType.getIdentifierMapping() ); return (TableUpdate) updateBuilder.buildMutation(); @@ -592,8 +579,7 @@ private void applyInsertRowValues( int rowPosition, SharedSessionContractImplementor session, JdbcValueBindings jdbcValueBindings) { - final PluralAttributeMapping attributeMapping = getAttributeMapping(); - + final var attributeMapping = getAttributeMapping(); attributeMapping.getKeyDescriptor().getKeyPart().decompose( keyValue, 0, @@ -602,9 +588,7 @@ private void applyInsertRowValues( RowMutationOperations.DEFAULT_VALUE_SETTER, session ); - - final CollectionPart indexDescriptor = attributeMapping.getIndexDescriptor(); - + final var indexDescriptor = attributeMapping.getIndexDescriptor(); if ( indexDescriptor != null ) { indexDescriptor.decompose( incrementIndexByBase( collection.getIndex( rowValue, rowPosition, this ) ), @@ -612,18 +596,17 @@ private void applyInsertRowValues( jdbcValueBindings, null, (valueIndex, bindings, noop, value, jdbcValueMapping) -> { - if ( !jdbcValueMapping.isUpdateable() ) { - return; + if ( jdbcValueMapping.isUpdateable() ) { + bindings.bindValue( value, jdbcValueMapping, ParameterUsage.SET ); } - bindings.bindValue( value, jdbcValueMapping, ParameterUsage.SET ); }, session ); } final Object elementValue = collection.getElement( rowValue ); - final EntityCollectionPart elementDescriptor = (EntityCollectionPart) attributeMapping.getElementDescriptor(); - final EntityIdentifierMapping identifierMapping = elementDescriptor.getAssociatedEntityMappingType().getIdentifierMapping(); + final var elementDescriptor = (EntityCollectionPart) attributeMapping.getElementDescriptor(); + final var identifierMapping = elementDescriptor.getAssociatedEntityMappingType().getIdentifierMapping(); identifierMapping.decompose( identifierMapping.getIdentifier( elementValue ), 0, @@ -636,25 +619,22 @@ private void applyInsertRowValues( private JdbcMutationOperation generateWriteIndexOperation(MutatingTableReference tableReference) { - // note that custom sql update details are handled by TableUpdateBuilderStandard + // note that custom SQL update details are handled by TableUpdateBuilderStandard final TableUpdateBuilderStandard updateBuilder = new TableUpdateBuilderStandard<>( this, tableReference, getFactory(), sqlWhereString ); - - final OneToManyCollectionPart elementDescriptor = (OneToManyCollectionPart) getAttributeMapping().getElementDescriptor(); + final var attributeMapping = getAttributeMapping(); + final var elementDescriptor = (OneToManyCollectionPart) attributeMapping.getElementDescriptor(); updateBuilder.addKeyRestrictionsLeniently( elementDescriptor.getAssociatedEntityMappingType().getIdentifierMapping() ); - // if the collection has an identifier, add its column as well - if ( getAttributeMapping().getIdentifierDescriptor() != null ) { - updateBuilder.addKeyRestrictionsLeniently( getAttributeMapping().getIdentifierDescriptor() ); + if ( attributeMapping.getIdentifierDescriptor() != null ) { + updateBuilder.addKeyRestrictionsLeniently( attributeMapping.getIdentifierDescriptor() ); } - // for each index column: // * add a restriction based on the previous value // * add an assignment for the new value - getAttributeMapping().getIndexDescriptor().forEachUpdatable( updateBuilder ); - - final RestrictedTableMutation tableUpdate = updateBuilder.buildMutation(); - return tableUpdate.createMutationOperation( null, getFactory() ); + attributeMapping.getIndexDescriptor().forEachUpdatable( updateBuilder ); + return updateBuilder.buildMutation() + .createMutationOperation( null, getFactory() ); } private void applyWriteIndexValues( @@ -686,12 +666,12 @@ private void applyWriteIndexRestrictions( int entryPosition, SharedSessionContractImplementor session, JdbcValueBindings jdbcValueBindings) { - final OneToManyCollectionPart elementDescriptor = (OneToManyCollectionPart) getAttributeMapping().getElementDescriptor(); - final EntityMappingType associatedType = elementDescriptor.getAssociatedEntityMappingType(); + final var attributeMapping = getAttributeMapping(); + final var elementDescriptor = (OneToManyCollectionPart) attributeMapping.getElementDescriptor(); + final var associatedType = elementDescriptor.getAssociatedEntityMappingType(); final Object element = collection.getElement( entry ); - final Object elementIdentifier = associatedType.getIdentifierMapping().getIdentifier( element ); associatedType.getIdentifierMapping().decompose( - elementIdentifier, + associatedType.getIdentifierMapping().getIdentifier( element ), 0, jdbcValueBindings, null, @@ -699,10 +679,9 @@ private void applyWriteIndexRestrictions( session ); - if ( getAttributeMapping().getIdentifierDescriptor() != null ) { - final Object identifier = collection.getIdentifier( entry, entryPosition ); - getAttributeMapping().getIdentifierDescriptor().decompose( - identifier, + if ( attributeMapping.getIdentifierDescriptor() != null ) { + attributeMapping.getIdentifierDescriptor().decompose( + collection.getIdentifier( entry, entryPosition ), 0, jdbcValueBindings, null, diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 059b0f09143f..7a93d10f7025 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -25,12 +25,9 @@ import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.boot.spi.SessionFactoryOptions; import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer; -import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor; import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor; import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementHelper; import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeDescriptor; -import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor; -import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributesMetadata; import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata; import org.hibernate.bytecode.spi.ReflectionOptimizer; import org.hibernate.cache.spi.access.EntityDataAccess; @@ -49,17 +46,14 @@ import org.hibernate.engine.internal.CacheHelper; import org.hibernate.engine.internal.ImmutableEntityEntryFactory; import org.hibernate.engine.internal.MutableEntityEntryFactory; -import org.hibernate.engine.jdbc.spi.JdbcCoordinator; import org.hibernate.engine.profile.internal.FetchProfileAffectee; import org.hibernate.engine.spi.CachedNaturalIdValueSource; import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.engine.spi.CollectionKey; import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.EntityEntryFactory; -import org.hibernate.engine.spi.EntityHolder; import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.LoadQueryInfluencers; -import org.hibernate.engine.spi.NaturalIdResolutions; import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistentAttributeInterceptable; import org.hibernate.engine.spi.SessionFactoryImplementor; @@ -75,19 +69,15 @@ import org.hibernate.generator.values.GeneratedValues; import org.hibernate.generator.values.GeneratedValuesMutationDelegate; import org.hibernate.generator.values.internal.GeneratedValuesHelper; -import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.id.BulkInsertionCapableIdentifierGenerator; import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.OptimizableGenerator; -import org.hibernate.id.enhanced.Optimizer; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.FilterAliasGenerator; import org.hibernate.internal.FilterHelper; import org.hibernate.internal.util.IndexedConsumer; import org.hibernate.internal.util.MarkerObject; import org.hibernate.internal.util.StringHelper; -import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.collections.LockModeEnumMap; import org.hibernate.jdbc.Expectation; import org.hibernate.loader.ast.internal.EntityConcreteTypeLoader; @@ -112,13 +102,9 @@ import org.hibernate.mapping.Component; import org.hibernate.mapping.DependantValue; import org.hibernate.mapping.Formula; -import org.hibernate.mapping.Join; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; -import org.hibernate.mapping.Selectable; -import org.hibernate.mapping.Subclass; import org.hibernate.mapping.Table; -import org.hibernate.mapping.Value; import org.hibernate.metamodel.UnsupportedMappingException; import org.hibernate.metamodel.mapping.Association; import org.hibernate.metamodel.mapping.AttributeMapping; @@ -134,7 +120,7 @@ import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.ManagedMappingType; -import org.hibernate.metamodel.mapping.internal.MappingModelHelper; +import org.hibernate.metamodel.mapping.MappingType; import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.NaturalIdMapping; import org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping; @@ -161,7 +147,6 @@ import org.hibernate.metamodel.mapping.internal.SimpleNaturalIdMapping; import org.hibernate.metamodel.mapping.internal.UnifiedAnyDiscriminatorConverter; import org.hibernate.metamodel.model.domain.NavigableRole; -import org.hibernate.metamodel.spi.EntityInstantiator; import org.hibernate.metamodel.spi.EntityRepresentationStrategy; import org.hibernate.metamodel.spi.MappingMetamodelImplementor; import org.hibernate.metamodel.spi.RuntimeModelCreationContext; @@ -189,7 +174,6 @@ import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy; import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategyProvider; -import org.hibernate.service.ServiceRegistry; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.Alias; import org.hibernate.sql.InFragment; @@ -218,22 +202,17 @@ 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; import org.hibernate.sql.ast.tree.select.SelectStatement; import org.hibernate.sql.exec.spi.JdbcOperation; import org.hibernate.sql.exec.spi.JdbcParametersList; -import org.hibernate.sql.model.MutationOperation; -import org.hibernate.sql.model.MutationOperationGroup; import org.hibernate.sql.model.ast.ColumnValueBinding; import org.hibernate.sql.model.ast.MutatingTableReference; import org.hibernate.sql.model.ast.builder.MutationGroupBuilder; import org.hibernate.sql.model.ast.builder.TableInsertBuilder; import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultCreationState; -import org.hibernate.sql.results.graph.Fetch; import org.hibernate.sql.results.graph.FetchParent; import org.hibernate.sql.results.graph.Fetchable; -import org.hibernate.sql.results.graph.FetchableContainer; import org.hibernate.sql.results.graph.entity.internal.EntityResultImpl; import org.hibernate.sql.results.graph.internal.ImmutableFetchList; import org.hibernate.sql.results.internal.SqlSelectionImpl; @@ -253,8 +232,6 @@ import org.hibernate.type.spi.TypeConfiguration; import java.io.Serializable; -import java.sql.PreparedStatement; -import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; @@ -290,8 +267,11 @@ import static org.hibernate.internal.util.StringHelper.isEmpty; import static org.hibernate.internal.util.StringHelper.qualify; import static org.hibernate.internal.util.StringHelper.qualifyConditionally; +import static org.hibernate.internal.util.StringHelper.root; import static org.hibernate.internal.util.StringHelper.unqualify; +import static org.hibernate.internal.util.collections.ArrayHelper.EMPTY_INT_ARRAY; import static org.hibernate.internal.util.collections.ArrayHelper.contains; +import static org.hibernate.internal.util.collections.ArrayHelper.indexOf; import static org.hibernate.internal.util.collections.ArrayHelper.isAllTrue; import static org.hibernate.internal.util.collections.ArrayHelper.to2DStringArray; import static org.hibernate.internal.util.collections.ArrayHelper.toIntArray; @@ -304,6 +284,11 @@ import static org.hibernate.internal.util.collections.CollectionHelper.toSmallList; import static org.hibernate.loader.ast.internal.MultiKeyLoadHelper.supportsSqlArrayType; import static org.hibernate.metamodel.RepresentationMode.POJO; +import static org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper.buildBasicAttributeMapping; +import static org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper.buildEncapsulatedCompositeIdentifierMapping; +import static org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper.buildNonEncapsulatedCompositeIdentifierMapping; +import static org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper.resolveAggregateColumnBasicType; +import static org.hibernate.metamodel.mapping.internal.MappingModelHelper.isCompatibleModelPart; 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; @@ -467,7 +452,7 @@ public AbstractEntityPersister( final EntityDataAccess cacheAccessStrategy, final NaturalIdDataAccess naturalIdRegionAccessStrategy, final RuntimeModelCreationContext creationContext) throws HibernateException { - this.jpaEntityName = persistentClass.getJpaEntityName(); + jpaEntityName = persistentClass.getJpaEntityName(); //set it here, but don't call it, since it's still uninitialized! factory = creationContext.getSessionFactory(); @@ -476,9 +461,9 @@ public AbstractEntityPersister( navigableRole = new NavigableRole( persistentClass.getEntityName() ); - final SessionFactoryOptions sessionFactoryOptions = creationContext.getSessionFactoryOptions(); + final var factoryOptions = creationContext.getSessionFactoryOptions(); - if ( sessionFactoryOptions.isSecondLevelCacheEnabled() ) { + if ( factoryOptions.isSecondLevelCacheEnabled() ) { this.cacheAccessStrategy = cacheAccessStrategy; this.naturalIdRegionAccessStrategy = naturalIdRegionAccessStrategy; canWriteToCache = determineCanWriteToCache( persistentClass, cacheAccessStrategy ); @@ -503,10 +488,8 @@ public AbstractEntityPersister( if ( isNotEmpty( persistentClass.getFilters() ) ) { filterHelper = new FilterHelper( persistentClass.getFilters(), - getEntityNameByTableNameMap( - persistentClass, - factory.getSqlStringGenerationContext() - ), + getEntityNameByTableNameMap( persistentClass, + factory.getSqlStringGenerationContext() ), factory ); } @@ -523,15 +506,17 @@ public AbstractEntityPersister( assert javaType != null; accessOptimizer = accessOptimizer( representationStrategy ); - concreteProxy = entityMetamodel.isPolymorphic() - && ( getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() || hasProxy() ) - && persistentClass.isConcreteProxy(); + concreteProxy = + entityMetamodel.isPolymorphic() + && ( getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() || hasProxy() ) + && persistentClass.isConcreteProxy(); - final Dialect dialect = creationContext.getDialect(); + final var dialect = creationContext.getDialect(); - batchSize = persistentClass.getBatchSize() < 0 - ? factory.getSessionFactoryOptions().getDefaultBatchFetchSize() - : persistentClass.getBatchSize(); + batchSize = + persistentClass.getBatchSize() < 0 + ? factoryOptions.getDefaultBatchFetchSize() + : persistentClass.getBatchSize(); hasSubselectLoadableCollections = persistentClass.hasSubselectLoadableCollections(); hasPartitionedSelectionMapping = persistentClass.hasPartitionedSelectionMapping(); hasCollectionNotReferencingPK = persistentClass.hasCollectionNotReferencingPK(); @@ -546,27 +531,29 @@ public AbstractEntityPersister( rootTableKeyColumnReaderTemplates = new String[identifierColumnSpan]; identifierAliases = new String[identifierColumnSpan]; - final String rowId = persistentClass.getRootTable().getRowId(); + final var rootTable = persistentClass.getRootTable(); + final String rowId = rootTable.getRowId(); rowIdName = rowId == null ? null : dialect.rowId( rowId ); queryLoaderName = persistentClass.getLoaderName(); - final TypeConfiguration typeConfiguration = creationContext.getTypeConfiguration(); + final var typeConfiguration = creationContext.getTypeConfiguration(); - final List columns = persistentClass.getIdentifier().getColumns(); + final var columns = persistentClass.getIdentifier().getColumns(); for (int i = 0; i < columns.size(); i++ ) { - final Column column = columns.get(i); + final var column = columns.get(i); rootTableKeyColumnNames[i] = column.getQuotedName( dialect ); rootTableKeyColumnReaders[i] = column.getReadExpr( dialect ); rootTableKeyColumnReaderTemplates[i] = column.getTemplate( dialect, typeConfiguration ); - identifierAliases[i] = column.getAlias( dialect, persistentClass.getRootTable() ); + identifierAliases[i] = column.getAlias( dialect, rootTable ); } // VERSION - versionColumnName = persistentClass.isVersioned() - ? persistentClass.getVersion().getColumns().get(0).getQuotedName( dialect ) - : null; + versionColumnName = + persistentClass.isVersioned() + ? persistentClass.getVersion().getColumns().get(0).getQuotedName( dialect ) + : null; //WHERE STRING @@ -575,20 +562,10 @@ public AbstractEntityPersister( sqlWhereStringTemplate = null; } else { - PersistentClass containingClass = persistentClass; - while ( containingClass.getSuperclass() != null ) { - final PersistentClass superclass = containingClass.getSuperclass(); - if ( !Objects.equals( persistentClass.getWhere(), superclass.getWhere() ) ) { - break; - } - containingClass = superclass; - } - sqlWhereStringTableExpression = determineTableName( containingClass.getTable() ); - sqlWhereStringTemplate = Template.renderWhereStringTemplate( - "(" + persistentClass.getWhere() + ")", - dialect, - typeConfiguration - ); + sqlWhereStringTableExpression = + determineTableName( getCountainingClass( persistentClass ).getTable() ); + sqlWhereStringTemplate = + renderSqlWhereStringTemplate( persistentClass, dialect, typeConfiguration ); } // PROPERTIES @@ -606,28 +583,27 @@ public AbstractEntityPersister( final ArrayList lazyNumbers = new ArrayList<>(); final ArrayList lazyTypes = new ArrayList<>(); - final List propertyClosure = persistentClass.getPropertyClosure(); + final var propertyClosure = persistentClass.getPropertyClosure(); boolean foundFormula = false; for ( int i = 0; i < propertyClosure.size(); i++ ) { - final Property prop = propertyClosure.get(i); - thisClassProperties.add( prop ); + final var property = propertyClosure.get(i); + thisClassProperties.add( property ); + final var propertyValue = property.getValue(); - final int span = prop.getColumnSpan(); + final int span = property.getColumnSpan(); final String[] colNames = new String[span]; final String[] colAliases = new String[span]; final String[] formulaTemplates = new String[span]; - final List selectables = prop.getSelectables(); + final var selectables = property.getSelectables(); for ( int k = 0; k < selectables.size(); k++ ) { - final Selectable selectable = selectables.get(k); - colAliases[k] = selectable.getAlias( dialect, prop.getValue().getTable() ); - if ( selectable.isFormula() ) { + final var selectable = selectables.get(k); + colAliases[k] = selectable.getAlias( dialect, propertyValue.getTable() ); + if ( selectable instanceof Formula formula ) { foundFormula = true; - final Formula formula = (Formula) selectable; formula.setFormula( substituteBrackets( formula.getFormula() ) ); formulaTemplates[k] = selectable.getTemplate( dialect, typeConfiguration ); } - else { - final Column column = (Column) selectable; + else if ( selectable instanceof Column column ) { colNames[k] = column.getQuotedName( dialect ); } } @@ -636,29 +612,29 @@ public AbstractEntityPersister( propertyColumnAliases[i] = colAliases; final boolean lazy = !EnhancementHelper.includeInBaseFetchGroup( - prop, + property, entityMetamodel.isInstrumented(), entityName -> { - final PersistentClass entityBinding = creationContext - .getMetadata() - .getEntityBinding( entityName ); + final var entityBinding = + creationContext.getMetadata() + .getEntityBinding( entityName ); assert entityBinding != null; return entityBinding.hasSubclasses(); }, - sessionFactoryOptions.isCollectionsInDefaultFetchGroupEnabled() + factoryOptions.isCollectionsInDefaultFetchGroupEnabled() ); if ( lazy ) { - lazyNames.add( prop.getName() ); + lazyNames.add( property.getName() ); lazyNumbers.add( i ); - lazyTypes.add( prop.getValue().getType() ); + lazyTypes.add( propertyValue.getType() ); } else { - nonLazyPropertyNames.add( prop.getName() ); + nonLazyPropertyNames.add( property.getName() ); } - propertyColumnUpdateable[i] = prop.getValue().getColumnUpdateability(); - propertyColumnInsertable[i] = prop.getValue().getColumnInsertability(); + propertyColumnUpdateable[i] = propertyValue.getColumnUpdateability(); + propertyColumnInsertable[i] = propertyValue.getColumnInsertability(); } hasFormulaProperties = foundFormula; lazyPropertyNames = toStringArray( lazyNames ); @@ -677,15 +653,15 @@ public AbstractEntityPersister( final ArrayList joinedFetchesList = new ArrayList<>(); if ( persistentClass.hasSubclasses() ) { - for ( Selectable selectable : persistentClass.getIdentifier().getSelectables() ) { - if ( !selectable.isFormula() ) { + for ( var selectable : persistentClass.getIdentifier().getSelectables() ) { + if ( selectable instanceof Column column ) { // Identifier columns are always shared between subclasses - sharedColumnNames.add( ( (Column) selectable ).getQuotedName( dialect ) ); + sharedColumnNames.add( column.getQuotedName( dialect ) ); } } } - for ( Property prop : persistentClass.getSubclassPropertyClosure() ) { + for ( var prop : persistentClass.getSubclassPropertyClosure() ) { names.add( prop.getName() ); types.add( prop.getType() ); @@ -694,10 +670,10 @@ public AbstractEntityPersister( final String[] readerTemplates = new String[ prop.getColumnSpan() ]; final String[] forms = new String[ prop.getColumnSpan() ]; - final List selectables = prop.getSelectables(); + final var selectables = prop.getSelectables(); for ( int i = 0; i < selectables.size(); i++ ) { - final Selectable selectable = selectables.get(i); - if ( selectable.isFormula() ) { + final var selectable = selectables.get(i); + if ( selectable instanceof Formula ) { final String template = selectable.getTemplate( dialect, typeConfiguration ); forms[i] = template; final String formulaAlias = selectable.getAlias( dialect ); @@ -705,20 +681,15 @@ public AbstractEntityPersister( formulaAliases.add( formulaAlias ); } } - else { - final Column column = (Column) selectable; + else if ( selectable instanceof Column column ) { final String colName = column.getQuotedName(dialect); cols[i] = colName; final String columnAlias = selectable.getAlias( dialect, prop.getValue().getTable() ); if ( prop.isSelectable() && !aliases.contains( columnAlias ) ) { aliases.add( columnAlias ); } - readers[i] = column.getReadExpr( dialect ); - readerTemplates[i] = column.getTemplate( - dialect, - typeConfiguration - ); + readerTemplates[i] = column.getTemplate( dialect, typeConfiguration ); if ( thisClassProperties.contains( prop ) ? persistentClass.hasSubclasses() : persistentClass.isDefinedOnMultipleSubclasses( column ) ) { @@ -749,19 +720,17 @@ public AbstractEntityPersister( subclassPropertyFetchModeClosure[j++] = fetchMode; } - useReferenceCacheEntries = shouldUseReferenceCacheEntries( creationContext.getSessionFactoryOptions() ); - useShallowQueryCacheLayout = shouldUseShallowCacheLayout( - persistentClass.getQueryCacheLayout(), - creationContext.getSessionFactoryOptions() - ); - storeDiscriminatorInShallowQueryCacheLayout = shouldStoreDiscriminatorInShallowQueryCacheLayout( - persistentClass.getQueryCacheLayout(), - creationContext.getSessionFactoryOptions() - ); - cacheEntryHelper = buildCacheEntryHelper( creationContext.getSessionFactoryOptions() ); - invalidateCache = sessionFactoryOptions.isSecondLevelCacheEnabled() - && canWriteToCache - && shouldInvalidateCache( persistentClass, creationContext ); + useReferenceCacheEntries = shouldUseReferenceCacheEntries( factoryOptions ); + final var queryCacheLayout = persistentClass.getQueryCacheLayout(); + useShallowQueryCacheLayout = + shouldUseShallowCacheLayout( queryCacheLayout, factoryOptions ); + storeDiscriminatorInShallowQueryCacheLayout = + shouldStoreDiscriminatorInShallowQueryCacheLayout( queryCacheLayout, factoryOptions ); + cacheEntryHelper = buildCacheEntryHelper( factoryOptions ); + invalidateCache = + factoryOptions.isSecondLevelCacheEnabled() + && canWriteToCache + && shouldInvalidateCache( persistentClass, creationContext ); final List values = new ArrayList<>(); final List sqlValues = new ArrayList<>(); @@ -772,9 +741,9 @@ public AbstractEntityPersister( sqlValues.add( DiscriminatorHelper.getDiscriminatorSQLValue( persistentClass, dialect ) ); } - final List subclasses = persistentClass.getSubclasses(); + final var subclasses = persistentClass.getSubclasses(); for ( int k = 0; k < subclasses.size(); k++ ) { - final Subclass subclass = subclasses.get( k ); + final var subclass = subclasses.get( k ); //copy/paste from EntityMetamodel: if ( !isAbstract( subclass ) ) { values.add( DiscriminatorHelper.getDiscriminatorValue( subclass ) ); @@ -791,8 +760,29 @@ public AbstractEntityPersister( } } + private static String renderSqlWhereStringTemplate( + PersistentClass persistentClass, Dialect dialect, TypeConfiguration typeConfiguration) { + return Template.renderWhereStringTemplate( + "(" + persistentClass.getWhere() + ")", + dialect, + typeConfiguration + ); + } + + private static PersistentClass getCountainingClass(PersistentClass persistentClass) { + var containingClass = persistentClass; + while ( containingClass.getSuperclass() != null ) { + final var superclass = containingClass.getSuperclass(); + if ( !Objects.equals( persistentClass.getWhere(), superclass.getWhere() ) ) { + break; + } + containingClass = superclass; + } + return containingClass; + } + private NamedQueryMemento getNamedQueryMemento(MetadataImplementor bootModel) { - final NamedQueryMemento memento = + final var memento = factory.getQueryEngine().getNamedObjectRepository() .resolve( factory, bootModel, queryLoaderName ); if ( memento == null ) { @@ -808,7 +798,7 @@ private NamedQueryMemento getNamedQueryMemento(MetadataImplementor bootModel) protected SingleIdEntityLoader buildSingleIdEntityLoader() { if ( hasNamedQueryLoader() ) { // We must resolve the named query on-demand through the boot model because it isn't initialized yet - final NamedQueryMemento memento = getNamedQueryMemento( null ); + final var memento = getNamedQueryMemento( null ); return new SingleIdEntityLoaderProvidedQueryImpl<>( this, memento ); } else { @@ -824,22 +814,19 @@ private SingleIdEntityLoader buildSingleIdEntityLoader( if ( lockOptions != null && needsOneOffLoader( lockOptions ) ) { return new SingleIdEntityLoaderStandardImpl<>( this, loadQueryInfluencers ); } - - if ( loadQueryInfluencers.effectivelyBatchLoadable( this ) ) { + else if ( loadQueryInfluencers.effectivelyBatchLoadable( this ) ) { final int batchSize = loadQueryInfluencers.effectiveBatchSize( this ); return factory.getServiceRegistry().requireService( BatchLoaderFactory.class ) .createEntityBatchLoader( batchSize, this, loadQueryInfluencers ); } - - return new SingleIdEntityLoaderStandardImpl<>( this, loadQueryInfluencers ); + else { + return new SingleIdEntityLoaderStandardImpl<>( this, loadQueryInfluencers ); + } } private boolean needsOneOffLoader(LockOptions lockOptions) { - if ( !lockOptions.getLockMode().isPessimistic() ) { - return false; - } - - return lockOptions.hasNonDefaultOptions(); + return lockOptions.getLockMode().isPessimistic() + && lockOptions.hasNonDefaultOptions(); } public static Map getEntityNameByTableNameMap( @@ -848,16 +835,18 @@ public static Map getEntityNameByTableNameMap( final Map entityNameByTableNameMap = new HashMap<>(); PersistentClass superType = persistentClass.getSuperPersistentClass(); while ( superType != null ) { - entityNameByTableNameMap.put( superType.getTable().getQualifiedName( stringGenerationContext ), superType.getEntityName() ); - for ( Join join : superType.getJoins() ) { - entityNameByTableNameMap.put( join.getTable().getQualifiedName( stringGenerationContext ), superType.getEntityName() ); + final String entityName = superType.getEntityName(); + entityNameByTableNameMap.put( superType.getTable().getQualifiedName( stringGenerationContext ), entityName ); + for ( var join : superType.getJoins() ) { + entityNameByTableNameMap.put( join.getTable().getQualifiedName( stringGenerationContext ), entityName ); } superType = superType.getSuperPersistentClass(); } - for ( PersistentClass subclass : persistentClass.getSubclassClosure() ) { - entityNameByTableNameMap.put( subclass.getTable().getQualifiedName( stringGenerationContext ), subclass.getEntityName() ); - for ( Join join : subclass.getJoins() ) { - entityNameByTableNameMap.put( join.getTable().getQualifiedName( stringGenerationContext ), subclass.getEntityName() ); + for ( var subclass : persistentClass.getSubclassClosure() ) { + final String entityName = subclass.getEntityName(); + entityNameByTableNameMap.put( subclass.getTable().getQualifiedName( stringGenerationContext ), entityName ); + for ( var join : subclass.getJoins() ) { + entityNameByTableNameMap.put( join.getTable().getQualifiedName( stringGenerationContext ), entityName ); } } return entityNameByTableNameMap; @@ -875,7 +864,8 @@ && supportsSqlArrayType( getDialect() ) private String getIdentitySelectString(Dialect dialect) { try { - final int idTypeCode = ((BasicType) getIdentifierType()).getJdbcType().getDdlTypeCode(); + final var identifierType = (BasicType) getIdentifierType(); + final int idTypeCode = identifierType.getJdbcType().getDdlTypeCode(); return dialect.getIdentityColumnSupport() .getIdentitySelectString( getTableName(0), getKeyColumns(0)[0], idTypeCode ); } @@ -905,8 +895,8 @@ else if ( entityMetamodel.isMutable() ) { else { // 2) have no associations. // Eventually we want to be a little more lenient with associations. - for ( Type type : getSubclassPropertyTypeClosure() ) { - if ( type instanceof AnyType || type instanceof CollectionType || type instanceof EntityType ) { + for ( var type : getSubclassPropertyTypeClosure() ) { + if ( type.isAnyType() || type.isCollectionType() || type.isEntityType() ) { return false; } } @@ -1118,7 +1108,7 @@ else if ( persistentClass.isCached() ) { return true; } else { - for ( Subclass subclass : persistentClass.getSubclasses() ) { + for ( var subclass : persistentClass.getSubclasses() ) { if ( subclass.isCached() ) { return true; } @@ -1179,25 +1169,26 @@ public Iterable uniqueKeyEntries() { return uniqueKeyEntries; } - private static List initUniqueKeyEntries(final AbstractEntityPersister aep) { + private static List initUniqueKeyEntries(final AbstractEntityPersister persister) { final ArrayList uniqueKeys = new ArrayList<>(); - for ( Type propertyType : aep.getPropertyTypes() ) { + for ( var propertyType : persister.getPropertyTypes() ) { if ( propertyType instanceof AssociationType associationType ) { final String ukName = associationType.getLHSPropertyName(); if ( ukName != null ) { - final AttributeMapping attributeMapping = aep.findAttributeMapping( ukName ); + final var attributeMapping = persister.findAttributeMapping( ukName ); if ( attributeMapping != null ) { final int index = attributeMapping.getStateArrayPosition(); - final Type type = aep.getPropertyTypes()[index]; + final Type type = persister.getPropertyTypes()[index]; uniqueKeys.add( new UniqueKeyEntry( ukName, index, type ) ); } } else if ( associationType instanceof ManyToOneType manyToOneType - && manyToOneType.isLogicalOneToOne() && manyToOneType.isReferenceToPrimaryKey() ) { - final AttributeMapping attributeMapping = aep.findAttributeMapping( manyToOneType.getPropertyName() ); + && manyToOneType.isLogicalOneToOne() + && manyToOneType.isReferenceToPrimaryKey() ) { + final var attributeMapping = persister.findAttributeMapping( manyToOneType.getPropertyName() ); if ( attributeMapping != null ) { final int index = attributeMapping.getStateArrayPosition(); - final Type type = aep.getPropertyTypes()[index]; + final Type type = persister.getPropertyTypes()[index]; uniqueKeys.add( new UniqueKeyEntry( manyToOneType.getPropertyName(), index, type ) ); } } @@ -1215,12 +1206,11 @@ protected Map getLazyLoadPlanByFetchGroup() { private Map createLazyLoadPlanByFetchGroup(BytecodeEnhancementMetadata metadata) { final Map result = new HashMap<>(); - final LazyAttributesMetadata attributesMetadata = metadata.getLazyAttributesMetadata(); + final var attributesMetadata = metadata.getLazyAttributesMetadata(); for ( String groupName : attributesMetadata.getFetchGroupNames() ) { - final SingleIdArrayLoadPlan loadPlan = - createLazyLoadPlan( attributesMetadata.getFetchGroupAttributeDescriptors( groupName ) ); - if ( loadPlan != null ) { - result.put( groupName, loadPlan ); + final var plan = createLazyLoadPlan( attributesMetadata.getFetchGroupAttributeDescriptors( groupName ) ); + if ( plan != null ) { + result.put( groupName, plan ); } } return result; @@ -1228,7 +1218,7 @@ private Map createLazyLoadPlanByFetchGroup(Byteco private SingleIdArrayLoadPlan createLazyLoadPlan(List fetchGroupAttributeDescriptors) { final List partsToSelect = new ArrayList<>( fetchGroupAttributeDescriptors.size() ); - for ( LazyAttributeDescriptor lazyAttributeDescriptor : fetchGroupAttributeDescriptors ) { + for ( var lazyAttributeDescriptor : fetchGroupAttributeDescriptors ) { // all this only really needs to consider properties // of this class, not its subclasses, but since we // are reusing code used for sequential selects, we @@ -1244,9 +1234,9 @@ private SingleIdArrayLoadPlan createLazyLoanPlan(List partsToSelect) return null; } else { - final LockOptions lockOptions = new LockOptions(); - final JdbcParametersList.Builder jdbcParametersBuilder = JdbcParametersList.newBuilder(); - final SelectStatement select = LoaderSelectBuilder.createSelect( + final var lockOptions = new LockOptions(); + final var jdbcParametersBuilder = JdbcParametersList.newBuilder(); + final var select = LoaderSelectBuilder.createSelect( this, partsToSelect, getIdentifierMapping(), @@ -1289,7 +1279,7 @@ public DomainResult createDomainResult( TableGroup tableGroup, String resultVariable, DomainResultCreationState creationState) { - final EntityResultImpl entityResult = new EntityResultImpl( + final var entityResult = new EntityResultImpl( navigablePath, this, tableGroup, @@ -1345,8 +1335,7 @@ public TableReferenceJoin createTableReferenceJoin( TableReference lhs, SqlAstCreationState creationState) { for ( int i = 1; i < getSubclassTableSpan(); i++ ) { - final String subclassTableName = getSubclassTableName( i ); - if ( subclassTableName.equals( joinTableExpression ) ) { + if ( getSubclassTableName( i ).equals( joinTableExpression ) ) { return generateTableReferenceJoin( lhs, joinTableExpression, @@ -1368,12 +1357,11 @@ protected TableReferenceJoin generateTableReferenceJoin( boolean innerJoin, String[] targetColumns, SqlAstCreationState creationState) { - final NamedTableReference joinedTableReference = new NamedTableReference( + final var joinedTableReference = new NamedTableReference( joinTableExpression, sqlAliasBase.generateNewAlias(), !innerJoin ); - return new TableReferenceJoin( innerJoin, joinedTableReference, @@ -1393,16 +1381,16 @@ protected Predicate generateJoinPredicate( String[] pkColumnNames, String[] fkColumnNames, SqlAstCreationState creationState) { - final EntityIdentifierMapping identifierMapping = getIdentifierMapping(); + final var identifierMapping = getIdentifierMapping(); - final Junction conjunction = new Junction( Junction.Nature.CONJUNCTION ); + final var conjunction = new Junction( Junction.Nature.CONJUNCTION ); assert pkColumnNames.length == fkColumnNames.length; assert pkColumnNames.length == identifierMapping.getJdbcTypeCount(); identifierMapping.forEachSelectable( (columnIndex, selection) -> { - final SqlExpressionResolver sqlExpressionResolver = creationState.getSqlExpressionResolver(); + final var sqlExpressionResolver = creationState.getSqlExpressionResolver(); final String rootPkColumnName = pkColumnNames[ columnIndex ]; final Expression pkColumnExpression = sqlExpressionResolver.resolveSqlExpression( @@ -1455,7 +1443,7 @@ private Object initializedLazyField( Object entity, SharedSessionContractImplementor session) { final Object id = session.getContextEntityIdentifier( entity ); - final EntityEntry entry = session.getPersistenceContext().getEntry( entity ); + final var entry = session.getPersistenceContext().getEntry( entity ); if ( entry == null ) { throw new HibernateException( "entity is not associated with the session: " + id ); } @@ -1470,9 +1458,9 @@ private Object initializedLazyField( // attempt to read it from second-level cache if ( session.getCacheMode().isGetEnabled() - && canReadFromCache() - && isLazyPropertiesCacheable() ) { - final EntityDataAccess cacheAccess = getCacheAccessStrategy(); + && canReadFromCache() + && isLazyPropertiesCacheable() ) { + final var cacheAccess = getCacheAccessStrategy(); final Object cacheKey = cacheAccess.generateCacheKey( id, @@ -1480,9 +1468,9 @@ && isLazyPropertiesCacheable() ) { session.getFactory(), session.getTenantIdentifier() ); - final Object ce = CacheHelper.fromSharedCache( session, cacheKey, this, cacheAccess ); - if ( ce != null ) { - final CacheEntry cacheEntry = (CacheEntry) getCacheEntryStructure().destructure( ce, factory ); + final Object structuredEntry = CacheHelper.fromSharedCache( session, cacheKey, this, cacheAccess ); + if ( structuredEntry != null ) { + final var cacheEntry = (CacheEntry) getCacheEntryStructure().destructure( structuredEntry, factory ); final Object initializedValue = initializeLazyPropertiesFromCache( fieldName, entity, session, entry, cacheEntry ); if ( initializedValue != LazyPropertyInitializer.UNFETCHED_PROPERTY ) { // The following should be redundant, since the setter should have set this already. @@ -1504,41 +1492,31 @@ private PersistentCollection initializedLazyCollection( SharedSessionContractImplementor session) { // a collection attribute is being accessed via enhancement: // we can circumvent all the rest and just return the PersistentCollection - final CollectionPersister persister = + final var persister = factory.getMappingMetamodel() .getCollectionDescriptor( collectionType.getRole() ); - // Get/create the collection, and make sure it is initialized! This initialized part is + // Get/create the collection, and make sure it is initialized! This initialized part is // different from proxy-based scenarios where we have to create the PersistentCollection - // reference "ahead of time" to add as a reference to the proxy. For bytecode solutions + // reference "ahead of time" to add as a reference to the proxy. For bytecode solutions // we are not creating the PersistentCollection ahead of time, but instead we are creating // it on first request through the enhanced entity. // see if there is already a collection instance associated with the session - // NOTE : can this ever happen? - final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); - final EntityEntry entry = persistenceContext.getEntry( entity ); - final Object key = getCollectionKey( persister, entity, entry, session ); - assert key != null; - PersistentCollection collection = - persistenceContext.getCollection( new CollectionKey( persister, key ) ); - if ( collection == null ) { - collection = collectionType.instantiate( session, persister, key ); - collection.setOwner( entity ); - persistenceContext.addUninitializedCollection( persister, collection, key ); - } + // NOTE: can this ever happen? + var collection = getCollection( entity, collectionType, session, persister ); final var interceptor = asPersistentAttributeInterceptable( entity ).$$_hibernate_getInterceptor(); assert interceptor != null : "Expecting bytecode interceptor to be non-null"; interceptor.attributeInitialized( fieldName ); + final var persistenceContext = session.getPersistenceContextInternal(); if ( collectionType.isArrayType() ) { persistenceContext.addCollectionHolder( collection ); } - - // update the "state" of the entity's EntityEntry to over-write UNFETCHED_PROPERTY reference - // for the collection to the just loaded collection - final EntityEntry ownerEntry = persistenceContext.getEntry( entity ); + // update the "state" of the owning entity's EntityEntry to overwrite the + // UNFETCHED_PROPERTY for the collection to the just-loaded collection + final var ownerEntry = persistenceContext.getEntry( entity ); if ( ownerEntry == null ) { // the entity is not in the session; it was probably deleted, // so we cannot load the collection anymore. @@ -1551,18 +1529,39 @@ private PersistentCollection initializedLazyCollection( return collection; } + private static PersistentCollection getCollection( + Object entity, + CollectionType collectionType, + SharedSessionContractImplementor session, + CollectionPersister persister) { + final var persistenceContext = session.getPersistenceContextInternal(); + final var entry = persistenceContext.getEntry( entity ); + final Object key = getCollectionKey( persister, entity, entry, session ); + assert key != null; + final var collection = persistenceContext.getCollection( new CollectionKey( persister, key ) ); + if ( collection == null ) { + final var newCollection = collectionType.instantiate( session, persister, key ); + newCollection.setOwner( entity ); + persistenceContext.addUninitializedCollection( persister, newCollection, key ); + return newCollection; + } + else { + return collection; + } + }; + public @Nullable static Object getCollectionKey( CollectionPersister persister, Object owner, EntityEntry ownerEntry, SharedSessionContractImplementor session) { - final CollectionType collectionType = persister.getCollectionType(); + final var collectionType = persister.getCollectionType(); if ( ownerEntry != null ) { // this call only works when the owner is associated with the Session, which is not always the case return collectionType.getKeyOfOwner( owner, session ); } else { - final EntityPersister ownerPersister = persister.getOwnerEntityPersister(); + final var ownerPersister = persister.getOwnerEntityPersister(); return collectionType.getLHSPropertyName() == null // collection key is defined by the owning entity identifier ? ownerPersister.getIdentifier( owner, session ) @@ -1604,11 +1603,10 @@ private Object initLazyProperties( final String fetchGroup = lazyAttributesMetadata.getFetchGroupName( fieldName ); final var fetchGroupAttributeDescriptors = lazyAttributesMetadata.getFetchGroupAttributeDescriptors( fetchGroup ); - - final SingleIdArrayLoadPlan lazySelect = getSQLLazySelectLoadPlan( fetchGroup ); + final var lazySelectLoadPlan = getSQLLazySelectLoadPlan( fetchGroup ); try { Object finalResult = null; - final Object[] results = lazySelect.load( id, session ); + final Object[] results = lazySelectLoadPlan.load( id, session ); int i = 0; for ( var fetchGroupAttributeDescriptor : fetchGroupAttributeDescriptors ) { final String attributeName = fetchGroupAttributeDescriptor.getName(); @@ -1655,12 +1653,11 @@ private Object initLazyProperty( // An eager property can be lazy because of an applied EntityGraph final int propertyIndex = getPropertyIndex( fieldName ); final List partsToSelect = List.of( getAttributeMapping( propertyIndex ) ); - final SingleIdArrayLoadPlan lazyLoanPlan = getOrCreateLazyLoadPlan( fieldName, partsToSelect ); + final var lazyLoanPlan = getOrCreateLazyLoadPlan( fieldName, partsToSelect ); try { final Object[] results = lazyLoanPlan.load( id, session ); final Object result = results[0]; - initializeLazyProperty( entity, entry, result, propertyIndex, - getPropertyTypes()[propertyIndex] ); + initializeLazyProperty( entity, entry, result, propertyIndex, getPropertyTypes()[propertyIndex] ); return result; } catch (JDBCException ex) { @@ -1674,25 +1671,19 @@ private Object initLazyProperty( } private SingleIdArrayLoadPlan getOrCreateLazyLoadPlan(String fieldName, List partsToSelect) { - var propertyLoadPlansByName = nonLazyPropertyLoadPlansByName; - if ( propertyLoadPlansByName == null ) { - propertyLoadPlansByName = new ConcurrentHashMap<>(); - final SingleIdArrayLoadPlan newLazyLoanPlan = createLazyLoanPlan( partsToSelect ); - propertyLoadPlansByName.put( fieldName, newLazyLoanPlan ); - nonLazyPropertyLoadPlansByName = propertyLoadPlansByName; - return newLazyLoanPlan; + final var plans = nonLazyPropertyLoadPlansByName; + if ( plans == null ) { + nonLazyPropertyLoadPlansByName = new ConcurrentHashMap<>(); } else { - final SingleIdArrayLoadPlan lazyLoanPlan = nonLazyPropertyLoadPlansByName.get( fieldName ); - if ( lazyLoanPlan == null ) { - final SingleIdArrayLoadPlan newLazyLoanPlan = createLazyLoanPlan( partsToSelect ); - nonLazyPropertyLoadPlansByName.put( fieldName, newLazyLoanPlan ); - return newLazyLoanPlan; - } - else { + final var lazyLoanPlan = plans.get( fieldName ); + if ( lazyLoanPlan != null ) { return lazyLoanPlan; } } + final var newLazyLoanPlan = createLazyLoanPlan( partsToSelect ); + nonLazyPropertyLoadPlansByName.put( fieldName, newLazyLoanPlan ); + return newLazyLoanPlan; } protected Object initializeLazyPropertiesFromCache( @@ -1703,19 +1694,17 @@ protected Object initializeLazyPropertiesFromCache( final CacheEntry cacheEntry) { LOG.trace( "Initializing lazy properties from second-level cache" ); Object result = null; - final Serializable[] disassembledValues = cacheEntry.getDisassembledState(); + final var disassembledValues = cacheEntry.getDisassembledState(); for ( int j = 0; j < lazyPropertyNames.length; j++ ) { - final Serializable cachedValue = disassembledValues[lazyPropertyNumbers[j]]; - final Type lazyPropertyType = lazyPropertyTypes[j]; - final String propertyName = lazyPropertyNames[j]; + final var cachedValue = disassembledValues[lazyPropertyNumbers[j]]; if ( cachedValue == LazyPropertyInitializer.UNFETCHED_PROPERTY ) { - if ( fieldName.equals(propertyName) ) { + if ( fieldName.equals( lazyPropertyNames[j] ) ) { result = LazyPropertyInitializer.UNFETCHED_PROPERTY; } // don't try to initialize the unfetched property } else { - final Object propValue = lazyPropertyType.assemble( cachedValue, session, entity ); + final Object propValue = lazyPropertyTypes[j].assemble( cachedValue, session, entity ); if ( initializeLazyProperty( fieldName, entity, entry, j, propValue ) ) { result = propValue; } @@ -1734,18 +1723,25 @@ protected boolean initializeLazyProperty( final EntityEntry entry, final int index, final Object propValue) { - setPropertyValue( entity, lazyPropertyNumbers[index], propValue ); - if ( entry.getLoadedState() != null ) { + final int propertyNumber = lazyPropertyNumbers[index]; + setPropertyValue( entity, propertyNumber, propValue ); + final var loadedState = entry.getLoadedState(); + if ( loadedState != null ) { // object have been loaded with setReadOnly(true); HHH-2236 - entry.getLoadedState()[lazyPropertyNumbers[index]] = lazyPropertyTypes[index].deepCopy( propValue, factory ); + loadedState[propertyNumber] = copiedLazyPropertyValue( index, propValue ); } // If the entity has deleted state, then update that as well - if ( entry.getDeletedState() != null ) { - entry.getDeletedState()[lazyPropertyNumbers[index]] = lazyPropertyTypes[index].deepCopy( propValue, factory ); + final var deletedState = entry.getDeletedState(); + if ( deletedState != null ) { + deletedState[propertyNumber] = copiedLazyPropertyValue( index, propValue ); } return fieldName.equals( lazyPropertyNames[index] ); } + private Object copiedLazyPropertyValue(int index, Object propValue) { + return lazyPropertyTypes[index].deepCopy( propValue, factory ); + } + // Used by Hibernate Reactive protected boolean initializeLazyProperty( final String fieldName, @@ -1763,13 +1759,13 @@ protected boolean initializeLazyProperty( // Used by Hibernate Reactive protected void initializeLazyProperty(Object entity, EntityEntry entry, Object propValue, int index, Type type) { setPropertyValue( entity, index, propValue ); - final Object[] loadedState = entry.getLoadedState(); + final var loadedState = entry.getLoadedState(); if ( loadedState != null ) { // object have been loaded with setReadOnly(true); HHH-2236 loadedState[index] = type.deepCopy( propValue, factory ); } // If the entity has deleted state, then update that as well - final Object[] deletedState = entry.getDeletedState(); + final var deletedState = entry.getDeletedState(); if ( deletedState != null ) { deletedState[index] = type.deepCopy( propValue, factory ); } @@ -1846,8 +1842,8 @@ public boolean isLazyPropertiesCacheable() { @Override public String selectFragment(String alias, String suffix) { - final QuerySpec rootQuerySpec = new QuerySpec( true ); - final LoaderSqlAstCreationState sqlAstCreationState = new LoaderSqlAstCreationState( + final var rootQuerySpec = new QuerySpec( true ); + final var sqlAstCreationState = new LoaderSqlAstCreationState( rootQuerySpec, new SqlAliasBaseManager(), new SimpleFromClauseAccessImpl(), @@ -1858,8 +1854,8 @@ public String selectFragment(String alias, String suffix) { factory.getSqlTranslationEngine() ); - final NavigablePath entityPath = new NavigablePath( getRootPathName() ); - final TableGroup rootTableGroup = createRootTableGroup( + final var entityPath = new NavigablePath( getRootPathName() ); + final var rootTableGroup = createRootTableGroup( true, entityPath, null, @@ -1874,13 +1870,12 @@ public String selectFragment(String alias, String suffix) { createDomainResult( entityPath, rootTableGroup, null, sqlAstCreationState ); // Wrap expressions with aliases - final SelectClause selectClause = rootQuerySpec.getSelectClause(); - final List sqlSelections = selectClause.getSqlSelections(); + final var sqlSelections = rootQuerySpec.getSelectClause().getSqlSelections(); final Set processedExpressions = new HashSet<>( sqlSelections.size() ); int i = 0; final int identifierSelectionSize = identifierMapping.getJdbcTypeCount(); for ( int j = 0; j < identifierSelectionSize; j++ ) { - final SelectableMapping selectableMapping = identifierMapping.getSelectable( j ); + final var selectableMapping = identifierMapping.getSelectable( j ); if ( processedExpressions.add( selectableMapping.getSelectionExpression() ) ) { aliasSelection( sqlSelections, i, identifierAliases[j] + suffix ); i++; @@ -1889,7 +1884,7 @@ public String selectFragment(String alias, String suffix) { if ( hasSubclasses() ) { assert discriminatorMapping.getJdbcTypeCount() == 1; - final SelectableMapping selectableMapping = discriminatorMapping.getSelectable( 0 ); + final var selectableMapping = discriminatorMapping.getSelectable( 0 ); if ( processedExpressions.add( selectableMapping.getSelectionExpression() ) ) { aliasSelection( sqlSelections, i, getDiscriminatorAlias() + suffix ); i++; @@ -1897,8 +1892,7 @@ public String selectFragment(String alias, String suffix) { } if ( hasRowId() ) { - final SelectableMapping selectableMapping = rowIdMapping; - if ( processedExpressions.add( selectableMapping.getSelectionExpression() ) ) { + if ( processedExpressions.add( rowIdMapping.getSelectionExpression() ) ) { aliasSelection( sqlSelections, i, ROWID_ALIAS + suffix ); i++; } @@ -1912,17 +1906,17 @@ public String selectFragment(String alias, String suffix) { // getSubclassColumnAliasClosure contains the _identifierMapper columns when it has an id class, // which need to be skipped if ( identifierMapping instanceof NonAggregatedIdentifierMapping nonAggregatedIdentifierMapping - && nonAggregatedIdentifierMapping.getIdClassEmbeddable() != null ) { + && nonAggregatedIdentifierMapping.getIdClassEmbeddable() != null ) { columnIndex = identifierSelectionSize; } for ( int j = 0; j < size; j++ ) { - final AttributeMapping fetchable = getFetchable( j ); + final var fetchable = getFetchable( j ); if ( !(fetchable instanceof PluralAttributeMapping) - && !skipFetchable( fetchable, fetchable.getMappedFetchOptions().getTiming() ) - && fetchable.isSelectable() ) { + && !skipFetchable( fetchable, fetchable.getMappedFetchOptions().getTiming() ) + && fetchable.isSelectable() ) { final int jdbcTypeCount = fetchable.getJdbcTypeCount(); for ( int k = 0; k < jdbcTypeCount; k++ ) { - final SelectableMapping selectableMapping = fetchable.getSelectable( k ); + final var selectableMapping = fetchable.getSelectable( k ); if ( processedExpressions.add( selectableMapping.getSelectionExpression() ) ) { final String baseAlias = selectableMapping.isFormula() ? formulaAliases[formulaIndex++] @@ -1949,28 +1943,26 @@ private static void aliasSelection( List sqlSelections, int selectionIndex, String alias) { - final Expression expression = sqlSelections.get( selectionIndex ).getExpression(); - sqlSelections.set( - selectionIndex, - new SqlSelectionImpl( selectionIndex, new AliasedExpression( expression, alias ) ) - ); + final var expression = sqlSelections.get( selectionIndex ).getExpression(); + sqlSelections.set( selectionIndex, + new SqlSelectionImpl( selectionIndex, new AliasedExpression( expression, alias ) ) ); } private ImmutableFetchList fetchProcessor(FetchParent fetchParent, LoaderSqlAstCreationState creationState) { - final FetchableContainer fetchableContainer = fetchParent.getReferencedMappingContainer(); + final var fetchableContainer = fetchParent.getReferencedMappingContainer(); final int size = fetchableContainer.getNumberOfFetchables(); - final ImmutableFetchList.Builder fetches = new ImmutableFetchList.Builder( fetchableContainer ); + final var fetches = new ImmutableFetchList.Builder( fetchableContainer ); for ( int i = 0; i < size; i++ ) { - final Fetchable fetchable = fetchableContainer.getFetchable( i ); + final var fetchable = fetchableContainer.getFetchable( i ); // Ignore plural attributes if ( !( fetchable instanceof PluralAttributeMapping ) ) { - final FetchTiming fetchTiming = fetchable.getMappedFetchOptions().getTiming(); + final var fetchTiming = fetchable.getMappedFetchOptions().getTiming(); if ( !skipFetchable( fetchable, fetchTiming ) ) { if ( fetchTiming == null ) { throw new AssertionFailure( "fetchTiming was null" ); } if ( fetchable.isSelectable() ) { - final Fetch fetch = fetchParent.generateFetchableFetch( + final var fetch = fetchParent.generateFetchableFetch( fetchable, fetchParent.resolveNavigablePath( fetchable ), fetchTiming, @@ -2034,11 +2026,8 @@ public Object[] getDatabaseSnapshot(Object id, SharedSessionContractImplementor @Override public Object getIdByUniqueKey(Object key, String uniquePropertyName, SharedSessionContractImplementor session) { if ( LOG.isTraceEnabled() ) { - LOG.tracef( - "resolving unique key [%s] to identifier for entity [%s]", - key, - getEntityName() - ); + LOG.tracef( "resolving unique key [%s] to identifier for entity [%s]", + key, getEntityName() ); } return getUniqueKeyLoader( uniquePropertyName, session ).resolveId( key, session ); @@ -2049,7 +2038,7 @@ public Object getIdByUniqueKey(Object key, String uniquePropertyName, SharedSess * Generate the SQL that selects the version number by id */ public String generateSelectVersionString() { - final SimpleSelect select = new SimpleSelect( getFactory() ).setTableName( getVersionedTableName() ); + final var select = new SimpleSelect( getFactory() ).setTableName( getVersionedTableName() ); if ( isVersioned() ) { select.addColumn( getVersionColumnName(), VERSION_COLUMN_ALIAS ); } @@ -2144,26 +2133,30 @@ public Object getCurrentVersion(Object id, SharedSessionContractImplementor sess } final String versionSelectString = getVersionSelectString(); try { - final JdbcCoordinator jdbcCoordinator = session.getJdbcCoordinator(); - final PreparedStatement st = jdbcCoordinator.getStatementPreparer().prepareStatement( versionSelectString ); + final var jdbcCoordinator = session.getJdbcCoordinator(); + final var statement = jdbcCoordinator.getStatementPreparer().prepareStatement( versionSelectString ); + final var resourceRegistry = jdbcCoordinator.getLogicalConnection().getResourceRegistry(); try { - getIdentifierType().nullSafeSet( st, id, 1, session ); - final ResultSet rs = jdbcCoordinator.getResultSetReturn().extract( st, versionSelectString ); + getIdentifierType().nullSafeSet( statement, id, 1, session ); + final var resultSet = jdbcCoordinator.getResultSetReturn().extract( statement, versionSelectString ); try { - if ( !rs.next() ) { + if ( !resultSet.next() ) { return null; } - if ( !isVersioned() ) { + else if ( !isVersioned() ) { return this; } - return getVersionMapping().getJdbcMapping().getJdbcValueExtractor().extract( rs, 1, session ); + else { + return getVersionMapping().getJdbcMapping().getJdbcValueExtractor() + .extract( resultSet, 1, session ); + } } finally { - jdbcCoordinator.getLogicalConnection().getResourceRegistry().release( rs, st ); + resourceRegistry.release( resultSet, statement ); } } finally { - jdbcCoordinator.getLogicalConnection().getResourceRegistry().release( st ); + resourceRegistry.release( statement ); jdbcCoordinator.afterStatementExecution(); } } @@ -2277,17 +2270,17 @@ public DiscriminatorType getDiscriminatorDomainType() { } private DiscriminatorType buildDiscriminatorType() { - final BasicType underlyingJdbcMapping = getDiscriminatorType(); - return underlyingJdbcMapping == null + final var discriminatorBasicType = getDiscriminatorType(); + return discriminatorBasicType == null ? null : new DiscriminatorTypeImpl<>( - underlyingJdbcMapping, + discriminatorBasicType, new UnifiedAnyDiscriminatorConverter<>( getNavigableRole() .append( EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME ), factory.getTypeConfiguration().getJavaTypeRegistry() .resolveDescriptor( discriminatedType() ), - underlyingJdbcMapping.getRelationalJavaType(), + discriminatorBasicType.getRelationalJavaType(), getSubclassByDiscriminatorValue(), null, factory.getMappingMetamodel() @@ -2316,7 +2309,7 @@ public static String generateTableAlias(String rootAlias, int tableNumber) { } private int getSubclassPropertyIndex(String propertyName) { - return ArrayHelper.indexOf( subclassPropertyNameClosure, propertyName ); + return indexOf( subclassPropertyNameClosure, propertyName ); } public String[] getPropertyColumnNames(int i) { @@ -2379,7 +2372,7 @@ private static boolean isPrefix(final AttributeMapping attributeMapping, final S @Override public int[] resolveAttributeIndexes(String[] attributeNames) { if ( attributeNames == null || attributeNames.length == 0 ) { - return ArrayHelper.EMPTY_INT_ARRAY; + return EMPTY_INT_ARRAY; } final List fields = new ArrayList<>( attributeNames.length ); @@ -2388,7 +2381,7 @@ public int[] resolveAttributeIndexes(String[] attributeNames) { int index = 0; for ( int i = 0; i < attributeMappings.size(); i++ ) { - final AttributeMapping attributeMapping = attributeMappings.get( i ); + final var attributeMapping = attributeMappings.get( i ); if ( isPrefix( attributeMapping, attributeNames[index] ) ) { fields.add( attributeMapping.getStateArrayPosition() ); index++; @@ -2419,10 +2412,13 @@ public int[] resolveDirtyAttributeIndexes( final String[] attributeNames, final SessionImplementor session) { final BitSet mutablePropertiesIndexes = entityMetamodel.getMutablePropertiesIndexes(); - final int estimatedSize = attributeNames == null ? 0 : attributeNames.length + mutablePropertiesIndexes.cardinality(); + final int estimatedSize = + attributeNames == null + ? 0 + : attributeNames.length + mutablePropertiesIndexes.cardinality(); final List fields = new ArrayList<>( estimatedSize ); if ( estimatedSize == 0 ) { - return ArrayHelper.EMPTY_INT_ARRAY; + return EMPTY_INT_ARRAY; } if ( !mutablePropertiesIndexes.isEmpty() ) { // We have to check the state for "mutable" properties as dirty tracking isn't aware of mutable types @@ -2461,7 +2457,7 @@ class ChildEntity extends SuperEntity { Arrays.sort( attributeNames ); int index = 0; for ( int i = 0; i < attributeMappings.size(); i++ ) { - final AttributeMapping attributeMapping = attributeMappings.get( i ); + final var attributeMapping = attributeMappings.get( i ); final String attributeName = attributeMapping.getAttributeName(); if ( isPrefix( attributeMapping, attributeNames[index] ) ) { final int position = attributeMapping.getStateArrayPosition(); @@ -2539,15 +2535,11 @@ public Object loadByUniqueKey( private Map> uniqueKeyLoadersNew; protected SingleUniqueKeyEntityLoader getUniqueKeyLoader(String attributeName, SharedSessionContractImplementor session) { - final SingularAttributeMapping attribute = (SingularAttributeMapping) findByPath( attributeName ); - final LoadQueryInfluencers influencers = session.getLoadQueryInfluencers(); + final var attribute = (SingularAttributeMapping) findByPath( attributeName ); + final var influencers = session.getLoadQueryInfluencers(); // no subselect fetching for entities for now if ( isAffectedByInfluencers( influencers, true ) ) { - return new SingleUniqueKeyEntityLoaderStandard<>( - this, - attribute, - influencers - ); + return new SingleUniqueKeyEntityLoaderStandard<>( this, attribute, influencers ); } final SingleUniqueKeyEntityLoader existing; if ( uniqueKeyLoadersNew == null ) { @@ -2563,7 +2555,8 @@ protected SingleUniqueKeyEntityLoader getUniqueKeyLoader(String attributeName } else { final SingleUniqueKeyEntityLoader loader = - new SingleUniqueKeyEntityLoaderStandard<>( this, attribute, new LoadQueryInfluencers( factory ) ); + new SingleUniqueKeyEntityLoaderStandard<>( this, attribute, + new LoadQueryInfluencers( factory ) ); uniqueKeyLoadersNew.put( attribute, loader ); return loader; } @@ -2589,7 +2582,7 @@ private void initOrdinaryPropertyPaths(Metadata mapping) throws MappingException } private void initIdentifierPropertyPaths(Metadata mapping) throws MappingException { - String idProp = getIdentifierPropertyName(); + final String idProp = getIdentifierPropertyName(); if ( idProp != null ) { propertyMapping.initPropertyPaths( idProp, getIdentifierType(), getIdentifierColumnNames(), @@ -2643,9 +2636,10 @@ public String getSelectByUniqueKeyString(String propertyName) { @Override public String getSelectByUniqueKeyString(String[] propertyNames) { - final SimpleSelect select = new SimpleSelect( getFactory() ) - .setTableName( getTableName(0) ) - .addColumns( getKeyColumns(0) ); + final var select = + new SimpleSelect( getFactory() ) + .setTableName( getTableName(0) ) + .addColumns( getKeyColumns(0) ); for ( String propertyName : propertyNames ) { select.addRestriction( getPropertyColumnNames( propertyName ) ); } @@ -2654,9 +2648,10 @@ public String getSelectByUniqueKeyString(String[] propertyNames) { @Override public String getSelectByUniqueKeyString(String[] propertyNames, String[] columnNames) { - final SimpleSelect select = new SimpleSelect( getFactory() ) - .setTableName( getTableName( 0 ) ) - .addColumns( columnNames ); + final var select = + new SimpleSelect( getFactory() ) + .setTableName( getTableName( 0 ) ) + .addColumns( columnNames ); for ( final String propertyName : propertyNames ) { select.addRestriction( getPropertyColumnNames( propertyName ) ); } @@ -2736,18 +2731,18 @@ protected void logStaticSQL() { if ( MODEL_MUTATION_LOGGER.isTraceEnabled() ) { MODEL_MUTATION_LOGGER.tracef( "Static SQL for entity: %s", getEntityName() ); for ( var entry : lazyLoadPlanByFetchGroup.entrySet() ) { - MODEL_MUTATION_LOGGER.tracef( " Lazy select (%s) : %s", entry.getKey(), entry.getValue().getJdbcSelect().getSqlString() ); + MODEL_MUTATION_LOGGER.tracef( " Lazy select (%s) : %s", + entry.getKey(), entry.getValue().getJdbcSelect().getSqlString() ); } if ( sqlVersionSelectString != null ) { MODEL_MUTATION_LOGGER.tracef( " Version select: %s", sqlVersionSelectString ); } { - final MutationOperationGroup staticInsertGroup = insertCoordinator.getStaticMutationOperationGroup(); + final var staticInsertGroup = insertCoordinator.getStaticMutationOperationGroup(); if ( staticInsertGroup != null ) { for ( int i = 0; i < staticInsertGroup.getNumberOfOperations(); i++ ) { - final MutationOperation mutation = staticInsertGroup.getOperation( i ); - if ( mutation instanceof JdbcOperation jdbcOperation ) { + if ( staticInsertGroup.getOperation( i ) instanceof JdbcOperation jdbcOperation ) { MODEL_MUTATION_LOGGER.tracef( " Insert (%s): %s", i, jdbcOperation.getSqlString() ); } } @@ -2755,11 +2750,10 @@ protected void logStaticSQL() { } { - final MutationOperationGroup staticUpdateGroup = updateCoordinator.getStaticMutationOperationGroup(); + final var staticUpdateGroup = updateCoordinator.getStaticMutationOperationGroup(); if ( staticUpdateGroup != null ) { for ( int i = 0; i < staticUpdateGroup.getNumberOfOperations(); i++ ) { - final MutationOperation mutation = staticUpdateGroup.getOperation( i ); - if ( mutation instanceof JdbcOperation jdbcOperation ) { + if ( staticUpdateGroup.getOperation( i ) instanceof JdbcOperation jdbcOperation ) { MODEL_MUTATION_LOGGER.tracef( " Update (%s): %s", i, jdbcOperation.getSqlString() ); } } @@ -2767,11 +2761,10 @@ protected void logStaticSQL() { } { - final MutationOperationGroup staticDeleteGroup = deleteCoordinator.getStaticMutationOperationGroup(); + final var staticDeleteGroup = deleteCoordinator.getStaticMutationOperationGroup(); if ( staticDeleteGroup != null ) { for ( int i = 0; i < staticDeleteGroup.getNumberOfOperations(); i++ ) { - final MutationOperation mutation = staticDeleteGroup.getOperation( i ); - if ( mutation instanceof JdbcOperation jdbcOperation ) { + if ( staticDeleteGroup.getOperation( i ) instanceof JdbcOperation jdbcOperation ) { MODEL_MUTATION_LOGGER.tracef( " Delete (%s): %s", i, jdbcOperation.getSqlString() ); } } @@ -2881,7 +2874,7 @@ public void applyDiscriminator( SqlAstCreationState creationState) { if ( needsDiscriminator() ) { assert !creationState.supportsEntityNameUsage() : "Entity name usage should have been used instead"; - final Collection subMappingTypes = getSubMappingTypes(); + final var subMappingTypes = getSubMappingTypes(); final Map entityNameUseMap = new HashMap<>( 1 + subMappingTypes.size() + ( isInherited() ? 1 : 0 ) ); if ( subMappingTypes.isEmpty() ) { @@ -2981,7 +2974,7 @@ else if ( hasNonNull ) { return new NullnessPredicate( sqlExpression, true ); } else if ( hasNull ) { - final Junction junction = new Junction( Junction.Nature.DISJUNCTION ); + final var junction = new Junction( Junction.Nature.DISJUNCTION ); junction.add( new NullnessPredicate( sqlExpression ) ); junction.add( discriminatorValuesPredicate( discriminatorType, sqlExpression ) ); return junction; @@ -3005,7 +2998,7 @@ protected String getPrunedDiscriminatorPredicate( Map entityNameUses, MappingMetamodelImplementor mappingMetamodel, String alias) { - final InFragment fragment = new InFragment(); + final var fragment = new InFragment(); if ( isDiscriminatorFormula() ) { fragment.setFormula( alias, getDiscriminatorFormulaTemplate() ); } @@ -3013,13 +3006,13 @@ protected String getPrunedDiscriminatorPredicate( fragment.setColumn( alias, getDiscriminatorColumnName() ); } boolean containsNotNull = false; - for ( Map.Entry entry : entityNameUses.entrySet() ) { - final EntityNameUse.UseKind useKind = entry.getValue().getKind(); + for ( var entry : entityNameUses.entrySet() ) { + final var useKind = entry.getValue().getKind(); if ( useKind == EntityNameUse.UseKind.PROJECTION || useKind == EntityNameUse.UseKind.EXPRESSION ) { // We only care about treat and filter uses which allow to reduce the amount of rows to select continue; } - final EntityPersister persister = mappingMetamodel.getEntityDescriptor( entry.getKey() ); + final var persister = mappingMetamodel.getEntityDescriptor( entry.getKey() ); // Filtering for abstract entities makes no sense, so ignore that // Also, it makes no sense to filter for any of the super types, // as the query will contain a filter for that already anyway @@ -3028,7 +3021,7 @@ protected String getPrunedDiscriminatorPredicate( fragment.addValue( persister.getDiscriminatorSQLValue() ); } } - final AbstractEntityPersister rootEntityDescriptor = (AbstractEntityPersister) getRootEntityDescriptor(); + final var rootEntityDescriptor = (AbstractEntityPersister) getRootEntityDescriptor(); final List discriminatorSQLValues = Arrays.asList( rootEntityDescriptor.fullDiscriminatorSQLValues ); if ( fragment.getValues().size() == discriminatorSQLValues.size() ) { // Nothing to prune if we filter for all subtypes @@ -3036,28 +3029,26 @@ protected String getPrunedDiscriminatorPredicate( } if ( containsNotNull ) { - final String lhs; - if ( isDiscriminatorFormula() ) { - lhs = StringHelper.replace( getDiscriminatorFormulaTemplate(), Template.TEMPLATE, alias ); - } - else { - lhs = qualifyConditionally( alias, getDiscriminatorColumnName() ); - } + final String lhs = isDiscriminatorFormula() + ? StringHelper.replace( getDiscriminatorFormulaTemplate(), Template.TEMPLATE, alias ) + : qualifyConditionally( alias, getDiscriminatorColumnName() ); final List actualDiscriminatorSQLValues = new ArrayList<>( discriminatorSQLValues.size() ); for ( String value : discriminatorSQLValues ) { if ( !fragment.getValues().contains( value ) && !InFragment.NULL.equals( value ) ) { actualDiscriminatorSQLValues.add( value ); } } - final StringBuilder sb = new StringBuilder( 70 + actualDiscriminatorSQLValues.size() * 10 ).append( " or " ); + final var sql = + new StringBuilder( 70 + actualDiscriminatorSQLValues.size() * 10 ) + .append( " or " ); if ( !actualDiscriminatorSQLValues.isEmpty() ) { - sb.append( lhs ).append( " is not in (" ); - sb.append( String.join( ",", actualDiscriminatorSQLValues ) ); - sb.append( ") and " ); + sql.append( lhs ).append( " is not in (" ); + sql.append( String.join( ",", actualDiscriminatorSQLValues ) ); + sql.append( ") and " ); } - sb.append( lhs ).append( " is not null" ); + sql.append( lhs ).append( " is not null" ); fragment.getValues().remove( InFragment.NOT_NULL ); - return fragment.toFragmentString() + sb; + return fragment.toFragmentString() + sql; } else { return fragment.toFragmentString(); @@ -3073,12 +3064,11 @@ public void applyFilterRestrictions( boolean onlyApplyLoadByKeyFilters, SqlAstCreationState creationState) { if ( filterHelper != null ) { - final FilterAliasGenerator filterAliasGenerator = useQualifier && tableGroup != null - ? getFilterAliasGenerator( tableGroup ) - : null; filterHelper.applyEnabledFilters( predicateConsumer, - filterAliasGenerator, + useQualifier && tableGroup != null + ? getFilterAliasGenerator( tableGroup ) + : null, enabledFilters, onlyApplyLoadByKeyFilters, tableGroup, @@ -3129,15 +3119,11 @@ private String getAliasInWhere(TableGroup tableGroup, boolean useQualifier) { return null; } else { - final TableReference tableReference = tableGroup.resolveTableReference( sqlWhereStringTableExpression ); - if ( tableReference == null ) { - return null; - } - else { - return useQualifier && tableReference.getIdentificationVariable() != null - ? tableReference.getIdentificationVariable() - : tableReference.getTableId(); - } + final var tableReference = tableGroup.resolveTableReference( sqlWhereStringTableExpression ); + return tableReference == null ? null : + useQualifier && tableReference.getIdentificationVariable() != null + ? tableReference.getIdentificationVariable() + : tableReference.getTableId(); } } @@ -3189,12 +3175,14 @@ public void prepareLoaders() { private void doLateInit() { tableMappings = buildTableMappings(); - final List insertGeneratedAttributes = hasInsertGeneratedProperties() ? - GeneratedValuesProcessor.getGeneratedAttributes( this, INSERT ) - : emptyList(); - final List updateGeneratedAttributes = hasUpdateGeneratedProperties() ? - GeneratedValuesProcessor.getGeneratedAttributes( this, UPDATE ) - : emptyList(); + final List insertGeneratedAttributes = + hasInsertGeneratedProperties() + ? GeneratedValuesProcessor.getGeneratedAttributes( this, INSERT ) + : emptyList(); + final List updateGeneratedAttributes = + hasUpdateGeneratedProperties() + ? GeneratedValuesProcessor.getGeneratedAttributes( this, UPDATE ) + : emptyList(); insertGeneratedProperties = initInsertGeneratedProperties( insertGeneratedAttributes ); updateGeneratedProperties = initUpdateGeneratedProperties( updateGeneratedAttributes ); @@ -3224,7 +3212,7 @@ private void doLateInit() { protected GeneratedValuesMutationDelegate createInsertDelegate() { if ( isIdentifierAssignedByInsert() ) { - final OnExecutionGenerator generator = (OnExecutionGenerator) getGenerator(); + final var generator = (OnExecutionGenerator) getGenerator(); return generator.getGeneratedIdentifierDelegate( this ); } return GeneratedValuesHelper.getGeneratedValuesDelegate( this, INSERT ); @@ -3577,28 +3565,27 @@ public Object initializeEnhancedEntityUsedAsProxy( if ( enhancementMetadata.extractLazyInterceptor( entity ) instanceof EnhancementAsProxyLazinessInterceptor proxyInterceptor ) { - final EntityKey entityKey = proxyInterceptor.getEntityKey(); + final var entityKey = proxyInterceptor.getEntityKey(); final Object identifier = entityKey.getIdentifier(); Object loaded = null; if ( canReadFromCache && session.isEventSource() ) { - final EventSource eventSource = (EventSource) session; + final var eventSource = (EventSource) session; loaded = eventSource.loadFromSecondLevelCache( this, entityKey, entity, LockMode.NONE ); } if ( loaded == null ) { - final LockOptions lockOptions = new LockOptions(); + final var lockOptions = new LockOptions(); loaded = determineLoaderToUse( session, lockOptions ).load( identifier, entity, lockOptions, session ); } if ( loaded == null ) { - final PersistenceContext persistenceContext = session.getPersistenceContext(); + final var persistenceContext = session.getPersistenceContext(); persistenceContext.removeEntry( entity ); persistenceContext.removeEntity( entityKey ); factory.getEntityNotFoundDelegate().handleEntityNotFound( entityKey.getEntityName(), identifier ); } - final LazyAttributeLoadingInterceptor interceptor = - enhancementMetadata.injectInterceptor( entity, identifier, session ); + final var interceptor = enhancementMetadata.injectInterceptor( entity, identifier, session ); final Object value; if ( nameOfAttributeBeingAccessed == null ) { @@ -3637,7 +3624,7 @@ public void registerAffectingFetchProfile(String fetchProfileName) { @Override public boolean isAffectedByEntityGraph(LoadQueryInfluencers loadQueryInfluencers) { - final RootGraphImplementor graph = loadQueryInfluencers.getEffectiveEntityGraph().getGraph(); + final var graph = loadQueryInfluencers.getEffectiveEntityGraph().getGraph(); return graph != null && graph.appliesTo( getFactory().getJpaMetamodel().entity( getEntityName() ) ); } @@ -3682,7 +3669,7 @@ public boolean isAffectedByEnabledFilters( @Override public int[] findDirty(Object[] currentState, Object[] previousState, Object entity, SharedSessionContractImplementor session) throws HibernateException { - int[] props = DirtyHelper.findDirty( + final int[] props = DirtyHelper.findDirty( entityMetamodel.getDirtyCheckablePropertyTypes(), currentState, previousState, @@ -3879,7 +3866,7 @@ public boolean hasLazyProperties() { public void afterReassociate(Object entity, SharedSessionContractImplementor session) { final var metadata = getBytecodeEnhancementMetadata(); if ( metadata.isEnhancedForLazyLoading() ) { - final BytecodeLazyAttributeInterceptor interceptor = metadata.extractLazyInterceptor( entity ); + final var interceptor = metadata.extractLazyInterceptor( entity ); if ( interceptor == null ) { metadata.injectInterceptor( entity, getIdentifier( entity, session ), session ); } @@ -3893,8 +3880,8 @@ public void afterReassociate(Object entity, SharedSessionContractImplementor ses private void handleNaturalIdReattachment(Object entity, SharedSessionContractImplementor session) { if ( naturalIdMapping != null ) { if ( naturalIdMapping.isMutable() ) { - final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); - final NaturalIdResolutions naturalIdResolutions = persistenceContext.getNaturalIdResolutions(); + final var persistenceContext = session.getPersistenceContextInternal(); + final var naturalIdResolutions = persistenceContext.getNaturalIdResolutions(); final Object id = getIdentifier( entity, session ); // for reattachment of mutable natural-ids, we absolutely positively have to grab the snapshot from the @@ -3933,19 +3920,19 @@ public Boolean isTransient(Object entity, SharedSessionContractImplementor sessi final Boolean isUnsaved = versionMapping.getUnsavedStrategy().isUnsaved( version ); if ( isUnsaved != null ) { if ( isUnsaved ) { - final PersistenceContext persistenceContext; - if ( version == null - && ( persistenceContext = session.getPersistenceContext() ).hasLoadContext() - && !persistenceContext.getLoadContexts().isLoadingFinished() ) { - // check if we're currently loading this entity instance, the version - // will be null but the entity cannot be considered transient - final EntityHolder holder = - persistenceContext.getEntityHolder( new EntityKey( id, this ) ); - if ( holder != null && holder.isEventuallyInitialized() && holder.getEntity() == entity ) { - return false; + if ( version == null ) { + final var persistenceContext = session.getPersistenceContext(); + if ( persistenceContext.hasLoadContext() + && !persistenceContext.getLoadContexts().isLoadingFinished() ) { + // check if we're currently loading this entity instance, the version + // will be null but the entity cannot be considered transient + final var holder = persistenceContext.getEntityHolder( new EntityKey( id, this ) ); + if ( holder != null && holder.isEventuallyInitialized() && holder.getEntity() == entity ) { + return false; + } } } - final Generator identifierGenerator = getGenerator(); + final var identifierGenerator = getGenerator(); if ( identifierGenerator != null ) { final Boolean unsaved = identifierMapping.getUnsavedStrategy().isUnsaved( id ); if ( unsaved != null && !unsaved ) { @@ -4054,12 +4041,14 @@ public EntityMappingType resolveConcreteProxyTypeForId(Object id, SharedSessionC if ( !concreteProxy ) { return this; } - - EntityConcreteTypeLoader concreteTypeLoader = this.concreteTypeLoader; - if ( concreteTypeLoader == null ) { - this.concreteTypeLoader = concreteTypeLoader = new EntityConcreteTypeLoader( this, session.getFactory() ); + else { + var concreteTypeLoader = this.concreteTypeLoader; + if ( concreteTypeLoader == null ) { + this.concreteTypeLoader = concreteTypeLoader = + new EntityConcreteTypeLoader( this, session.getFactory() ); + } + return concreteTypeLoader.getConcreteType( id, session ); } - return concreteTypeLoader.getConcreteType( id, session ); } /** @@ -4126,14 +4115,14 @@ private Generator versionPropertyGenerator() { } public boolean isVersionGeneratedOnExecution() { - final Generator strategy = versionPropertyGenerator(); + final var strategy = versionPropertyGenerator(); return strategy != null && strategy.generatesSometimes() && strategy.generatedOnExecution(); } public boolean isVersionGeneratedBeforeExecution() { - final Generator strategy = versionPropertyGenerator(); + final var strategy = versionPropertyGenerator(); return strategy != null && strategy.generatesSometimes() && !strategy.generatedOnExecution(); @@ -4215,7 +4204,7 @@ public final Class getMappedClass() { @Override public Class getConcreteProxyClass() { - final JavaType proxyJavaType = getRepresentationStrategy().getProxyJavaType(); + final var proxyJavaType = getRepresentationStrategy().getProxyJavaType(); return proxyJavaType != null ? proxyJavaType.getJavaTypeClass() : javaType.getJavaTypeClass(); } @@ -4225,9 +4214,9 @@ public void setPropertyValues(Object object, Object[] values) { accessOptimizer.setPropertyValues( object, values ); } else { - final AttributeMappingsList attributeMappings = getAttributeMappings(); + final int size = getAttributeMappings().size(); if ( getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() ) { - for ( int i = 0; i < attributeMappings.size(); i++ ) { + for ( int i = 0; i < size; i++ ) { final Object value = values[i]; if ( value != UNFETCHED_PROPERTY ) { setterCache[i].set( object, value ); @@ -4235,7 +4224,7 @@ public void setPropertyValues(Object object, Object[] values) { } } else { - for ( int i = 0; i < attributeMappings.size(); i++ ) { + for ( int i = 0; i < size; i++ ) { setterCache[i].set( object, values[i] ); } } @@ -4254,12 +4243,12 @@ public Object[] getPropertyValues(Object object) { } else { final var enhancementMetadata = getBytecodeEnhancementMetadata(); - final AttributeMappingsList attributeMappings = getAttributeMappings(); + final var attributeMappings = getAttributeMappings(); final Object[] values = new Object[attributeMappings.size()]; if ( enhancementMetadata.isEnhancedForLazyLoading() ) { final var lazyAttributesMetadata = enhancementMetadata.getLazyAttributesMetadata(); for ( int i = 0; i < attributeMappings.size(); i++ ) { - final AttributeMapping attributeMapping = attributeMappings.get( i ); + final var attributeMapping = attributeMappings.get( i ); if ( !lazyAttributesMetadata.isLazyAttribute( attributeMapping.getAttributeName() ) || enhancementMetadata.isAttributeLoaded( object, attributeMapping.getAttributeName() ) ) { values[i] = getterCache[i].get( object ); @@ -4285,50 +4274,49 @@ public Object getPropertyValue(Object object, int i) { } @Override - public Object getPropertyValue(Object object, String propertyName) { - final int dotIndex = propertyName.indexOf( '.' ); - final String basePropertyName = dotIndex == -1 - ? propertyName - : propertyName.substring( 0, dotIndex ); - final AttributeMapping attributeMapping = findAttributeMapping( basePropertyName ); - ManagedMappingType baseValueType = null; - Object baseValue = null; + public Object getPropertyValue(Object object, String path) { + final String basePropertyName = root( path ); + final boolean isBasePath = basePropertyName.length() == path.length(); + final var attributeMapping = findAttributeMapping( basePropertyName ); + final Object baseValue; + final MappingType baseValueType; if ( attributeMapping != null ) { - baseValue = getterCache[attributeMapping.getStateArrayPosition()].get( object ); - if ( dotIndex != -1 ) { - baseValueType = (ManagedMappingType) attributeMapping.getMappedType(); - } + baseValue = getterCache[ attributeMapping.getStateArrayPosition() ].get( object ); + baseValueType = attributeMapping.getMappedType(); } else if ( identifierMapping instanceof NonAggregatedIdentifierMapping nonAggregatedIdentifierMapping ) { - final AttributeMapping mapping = - nonAggregatedIdentifierMapping.findSubPart( propertyName, null ) + final var mapping = + nonAggregatedIdentifierMapping.findSubPart( path, null ) .asAttributeMapping(); - if ( mapping != null ) { - baseValue = mapping.getValue( object ); - if ( dotIndex != -1 ) { - baseValueType = (ManagedMappingType) mapping.getMappedType(); - } - } + baseValue = mapping == null ? null : mapping.getValue( object ); + baseValueType = mapping == null ? null : mapping.getMappedType(); + } + else { + baseValue = null; + baseValueType = null; } - return getPropertyValue( baseValue, baseValueType, propertyName, dotIndex ); + return isBasePath + ? baseValue + : getPropertyValue( baseValue, (ManagedMappingType) baseValueType, path, basePropertyName ); } private Object getPropertyValue( Object baseValue, ManagedMappingType baseValueType, - String propertyName, - int dotIndex) { + String path, + String prefix) { if ( baseValueType == null ) { + // TODO: is this necessary? Should it be an exception instead? return baseValue; } else { - final int nextDotIndex = propertyName.indexOf( '.', dotIndex + 1 ); - final int endIndex = nextDotIndex == -1 ? propertyName.length() : nextDotIndex; - final AttributeMapping attributeMapping = - baseValueType.findAttributeMapping( propertyName.substring( dotIndex + 1, endIndex ) ); - baseValue = attributeMapping.getValue( baseValue ); - baseValueType = nextDotIndex == -1 ? null : (ManagedMappingType) attributeMapping.getMappedType(); - return getPropertyValue( baseValue, baseValueType, propertyName, nextDotIndex ); + final int afterDot = prefix.length() + 1; + final int nextDotIndex = path.indexOf( '.', afterDot ); + final String pathSoFar = nextDotIndex < 0 ? path : path.substring( 0, nextDotIndex ); + final var attributeMapping = baseValueType.findAttributeMapping( pathSoFar.substring( afterDot ) ); + final var value = attributeMapping.getValue( baseValue ); + final var type = nextDotIndex < 0 ? null : (ManagedMappingType) attributeMapping.getMappedType(); + return getPropertyValue( value, type, path, pathSoFar ); } } @@ -4349,8 +4337,9 @@ public void setIdentifier(Object entity, Object id, SharedSessionContractImpleme @Override public Object getVersion(Object object) { - return getVersionMapping() == null ? null - : getVersionMapping().getVersionAttribute().getPropertyAccess().getGetter().get( object ); + final var versionMapping = getVersionMapping(); + return versionMapping == null ? null + : versionMapping.getVersionAttribute().getPropertyAccess().getGetter().get( object ); } @Override @@ -4413,8 +4402,8 @@ && hasSubclasses() && !getRepresentationStrategy().getInstantiator().isSameClass( instance ) ) { // todo (6.0) : this previously used `org.hibernate.tuple.entity.EntityTuplizer#determineConcreteSubclassEntityName` // - we may need something similar here... - for ( EntityMappingType subclassMappingType : subclassMappingTypes.values() ) { - final EntityPersister persister = subclassMappingType.getEntityPersister(); + for ( var subclassMappingType : subclassMappingTypes.values() ) { + final var persister = subclassMappingType.getEntityPersister(); if ( persister.getRepresentationStrategy().getInstantiator().isSameClass( instance ) ) { return persister; } @@ -4437,7 +4426,7 @@ public Object[] getPropertyValuesToInsert( Object entity, Map mergeMap, SharedSessionContractImplementor session) - throws HibernateException { + throws HibernateException { if ( shouldGetAllProperties( entity ) && accessOptimizer != null ) { return accessOptimizer.getPropertyValues( entity ); } @@ -4472,7 +4461,7 @@ public void processInsertGeneratedProperties( protected List initInsertGeneratedProperties(List generatedAttributes) { final int originalSize = generatedAttributes.size(); final List generatedBasicAttributes = new ArrayList<>( originalSize ); - for ( AttributeMapping generatedAttribute : generatedAttributes ) { + for ( var generatedAttribute : generatedAttributes ) { // todo (7.0) : support non selectable mappings? Component, ToOneAttributeMapping, ... if ( generatedAttribute.asBasicValuedModelPart() != null && generatedAttribute.getContainingTableExpression().equals( getRootTableName() ) ) { @@ -4510,7 +4499,7 @@ public void processUpdateGeneratedProperties( protected List initUpdateGeneratedProperties(List generatedAttributes) { final int originalSize = generatedAttributes.size(); final List generatedBasicAttributes = new ArrayList<>( originalSize ); - for ( AttributeMapping generatedAttribute : generatedAttributes ) { + for ( var generatedAttribute : generatedAttributes ) { if ( generatedAttribute instanceof SelectableMapping selectableMapping && selectableMapping.getContainingTableExpression().equals( getSubclassTableName( 0 ) ) ) { generatedBasicAttributes.add( generatedAttribute ); @@ -4777,25 +4766,25 @@ private void handleSubtypeMappings(MappingModelCreationProcess creationProcess) } private static ReflectionOptimizer.AccessOptimizer accessOptimizer(EntityRepresentationStrategy strategy) { - final ReflectionOptimizer reflectionOptimizer = strategy.getReflectionOptimizer(); + final var reflectionOptimizer = strategy.getReflectionOptimizer(); return reflectionOptimizer == null ? null : reflectionOptimizer.getAccessOptimizer(); } private void prepareMappings(MappingModelCreationProcess creationProcess) { - final PersistentClass bootEntityDescriptor = + final var persistentClass = creationProcess.getCreationContext().getBootModel() .getEntityBinding( getEntityName() ); - initializeSpecialAttributeMappings( creationProcess, bootEntityDescriptor ); + initializeSpecialAttributeMappings( creationProcess, persistentClass ); versionGenerator = createVersionGenerator( entityMetamodel, versionMapping ); - buildDeclaredAttributeMappings( creationProcess, bootEntityDescriptor ); + buildDeclaredAttributeMappings( creationProcess, persistentClass ); getAttributeMappings(); - initializeNaturalIdMapping( creationProcess, bootEntityDescriptor ); + initializeNaturalIdMapping( creationProcess, persistentClass ); } private void initializeSpecialAttributeMappings (MappingModelCreationProcess creationProcess, PersistentClass bootEntityDescriptor) { if ( superMappingType != null ) { - ((InFlightEntityMappingType) superMappingType).prepareMappingModel( creationProcess ); + ( (InFlightEntityMappingType) superMappingType ).prepareMappingModel( creationProcess ); if ( shouldProcessSuperMapping() ) { inheritSupertypeSpecialAttributeMappings(); } @@ -4819,14 +4808,14 @@ private void inheritSupertypeSpecialAttributeMappings() { private void buildDeclaredAttributeMappings (MappingModelCreationProcess creationProcess, PersistentClass bootEntityDescriptor) { + final var properties = entityMetamodel.getProperties(); + final var mappingsBuilder = AttributeMappingsMap.builder(); int stateArrayPosition = getStateArrayInitialPosition( creationProcess ); - final NonIdentifierAttribute[] properties = entityMetamodel.getProperties(); - final AttributeMappingsMap.Builder mappingsBuilder = AttributeMappingsMap.builder(); int fetchableIndex = getFetchableIndexOffset(); for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) { - final NonIdentifierAttribute runtimeAttributeDefinition = properties[i]; + final var runtimeAttributeDefinition = properties[i]; final String attributeName = runtimeAttributeDefinition.getName(); - final Property bootProperty = bootEntityDescriptor.getProperty( attributeName ); + final var bootProperty = bootEntityDescriptor.getProperty( attributeName ); if ( superMappingType == null || superMappingType.findAttributeMapping( bootProperty.getName() ) == null ) { mappingsBuilder.put( @@ -4848,7 +4837,7 @@ private void inheritSupertypeSpecialAttributeMappings() { private static BeforeExecutionGenerator createVersionGenerator (EntityMetamodel currentEntityMetamodel, EntityVersionMapping versionMapping) { if ( currentEntityMetamodel.isVersioned() ) { - final BeforeExecutionGenerator generator = currentEntityMetamodel.getVersionGenerator(); + final var generator = currentEntityMetamodel.getVersionGenerator(); // need to do this here because EntityMetamodel doesn't have the EntityVersionMapping :-( return generator == null ? new VersionGeneration( versionMapping ) : generator; } @@ -4903,10 +4892,10 @@ private boolean isSubselect() { } private boolean generatorNeedsMultiTableInsert() { - final Generator generator = getGenerator(); + final var generator = getGenerator(); if ( generator instanceof BulkInsertionCapableIdentifierGenerator && generator instanceof OptimizableGenerator optimizableGenerator ) { - final Optimizer optimizer = optimizableGenerator.getOptimizer(); + final var optimizer = optimizableGenerator.getOptimizer(); return optimizer != null && optimizer.getIncrementSize() > 1; } else { @@ -4916,9 +4905,9 @@ private boolean generatorNeedsMultiTableInsert() { private int getFetchableIndexOffset() { if ( superMappingType != null ) { - final EntityMappingType rootEntityDescriptor = getRootEntityDescriptor(); + final var rootEntityDescriptor = getRootEntityDescriptor(); int offset = rootEntityDescriptor.getNumberOfDeclaredAttributeMappings(); - for ( EntityMappingType subMappingType : rootEntityDescriptor.getSubMappingTypes() ) { + for ( var subMappingType : rootEntityDescriptor.getSubMappingTypes() ) { if ( subMappingType == this ) { break; } @@ -4938,25 +4927,21 @@ private int getFetchableIndexOffset() { } private void prepareMappingModel(MappingModelCreationProcess creationProcess, PersistentClass bootEntityDescriptor) { - final EntityInstantiator instantiator = getRepresentationStrategy().getInstantiator(); + final var instantiator = getRepresentationStrategy().getInstantiator(); final Supplier instantiate = instantiator.canBeInstantiated() ? instantiator::instantiate : null; - identifierMapping = creationProcess.processSubPart( EntityIdentifierMapping.ID_ROLE_NAME, - (role, process) -> generateIdentifierMapping( instantiate, bootEntityDescriptor, process ) ); + identifierMapping = + creationProcess.processSubPart( EntityIdentifierMapping.ID_ROLE_NAME, + (role, process) -> generateIdentifierMapping( instantiate, bootEntityDescriptor, process ) ); versionMapping = generateVersionMapping( instantiate, bootEntityDescriptor, creationProcess ); rowIdMapping = rowIdName == null ? null : creationProcess.processSubPart( rowIdName, (role, process) -> new EntityRowIdMappingImpl( rowIdName, getTableName(), this ) ); discriminatorMapping = generateDiscriminatorMapping( bootEntityDescriptor ); - softDeleteMapping = resolveSoftDeleteMapping( - this, - bootEntityDescriptor.getRootClass(), - getIdentifierTableName(), - creationProcess - ); - if ( softDeleteMapping != null ) { - if ( bootEntityDescriptor.getRootClass().getCustomSQLDelete() != null ) { - throw new UnsupportedMappingException( "Entity may not define both @SoftDelete and @SQLDelete" ); - } + final var rootClass = bootEntityDescriptor.getRootClass(); + softDeleteMapping = + resolveSoftDeleteMapping( this, rootClass, getIdentifierTableName(), creationProcess ); + if ( softDeleteMapping != null && rootClass.getCustomSQLDelete() != null ) { + throw new UnsupportedMappingException( "Entity may not define both @SoftDelete and @SQLDelete" ); } } @@ -4983,9 +4968,8 @@ else if ( bootEntityDescriptor.hasNaturalId() ) { if ( naturalIdAttributeIndexes.length == 1 ) { final String propertyName = entityMetamodel.getPropertyNames()[ naturalIdAttributeIndexes[ 0 ] ]; - final AttributeMapping attributeMapping = findAttributeMapping( propertyName ); - final SingularAttributeMapping singularAttributeMapping = (SingularAttributeMapping) attributeMapping; - return new SimpleNaturalIdMapping( singularAttributeMapping, this, creationProcess ); + final var attributeMapping = (SingularAttributeMapping) findAttributeMapping( propertyName ); + return new SimpleNaturalIdMapping( attributeMapping, this, creationProcess ); } // collect the names of the attributes making up the natural-id. @@ -4999,7 +4983,7 @@ else if ( bootEntityDescriptor.hasNaturalId() ) { final List collectedAttrMappings = new ArrayList<>(); for ( int i = 0; i < attributeMappings.size(); i++ ) { - final AttributeMapping attributeMapping = attributeMappings.get( i ); + final var attributeMapping = attributeMappings.get( i ); if ( attributeNames.contains( attributeMapping.getAttributeName() ) ) { collectedAttrMappings.add( (SingularAttributeMapping) attributeMapping ); } @@ -5016,26 +5000,24 @@ protected static SqmMultiTableMutationStrategy interpretSqmMultiTableStrategy( AbstractEntityPersister entityMappingDescriptor, MappingModelCreationProcess creationProcess) { assert entityMappingDescriptor.hasMultipleTables(); - - final EntityMappingType superMappingType = entityMappingDescriptor.getSuperMappingType(); + final var superMappingType = entityMappingDescriptor.getSuperMappingType(); if ( superMappingType != null ) { - final SqmMultiTableMutationStrategy sqmMultiTableMutationStrategy = + final var sqmMultiTableMutationStrategy = superMappingType.getSqmMultiTableMutationStrategy(); if ( sqmMultiTableMutationStrategy != null ) { return sqmMultiTableMutationStrategy; } } - - final ServiceRegistry serviceRegistry = creationProcess.getCreationContext().getServiceRegistry(); - return serviceRegistry.requireService( SqmMultiTableMutationStrategyProvider.class ) + return creationProcess.getCreationContext().getServiceRegistry() + .requireService( SqmMultiTableMutationStrategyProvider.class ) .createMutationStrategy( entityMappingDescriptor, creationProcess ); } protected static SqmMultiTableInsertStrategy interpretSqmMultiTableInsertStrategy( AbstractEntityPersister entityMappingDescriptor, MappingModelCreationProcess creationProcess) { - final ServiceRegistry serviceRegistry = creationProcess.getCreationContext().getServiceRegistry(); - return serviceRegistry.requireService( SqmMultiTableMutationStrategyProvider.class ) + return creationProcess.getCreationContext().getServiceRegistry() + .requireService( SqmMultiTableMutationStrategyProvider.class ) .createInsertStrategy( entityMappingDescriptor, creationProcess ); } @@ -5076,10 +5058,13 @@ protected EntityDiscriminatorMapping generateDiscriminatorMapping(PersistentClas final Integer arrayLength; final Integer precision; final Integer scale; - if ( getDiscriminatorFormulaTemplate() == null ) { - final Column column = bootEntityDescriptor.getDiscriminator() == null - ? null - : bootEntityDescriptor.getDiscriminator().getColumns().get( 0 ); + final String discriminatorFormulaTemplate = getDiscriminatorFormulaTemplate(); + if ( discriminatorFormulaTemplate == null ) { + final var discriminator = bootEntityDescriptor.getDiscriminator(); + final Column column = + discriminator == null + ? null + : discriminator.getColumns().get( 0 ); discriminatorColumnExpression = getDiscriminatorColumnReaders(); if ( column == null ) { columnDefinition = null; @@ -5097,7 +5082,7 @@ protected EntityDiscriminatorMapping generateDiscriminatorMapping(PersistentClas } } else { - discriminatorColumnExpression = getDiscriminatorFormulaTemplate(); + discriminatorColumnExpression = discriminatorFormulaTemplate; columnDefinition = null; length = null; arrayLength = null; @@ -5109,7 +5094,7 @@ protected EntityDiscriminatorMapping generateDiscriminatorMapping(PersistentClas discriminatorColumnExpression, getTableName(), discriminatorColumnExpression, - getDiscriminatorFormulaTemplate() != null, + discriminatorFormulaTemplate != null, isPhysicalDiscriminator(), false, columnDefinition, @@ -5154,7 +5139,7 @@ protected boolean shouldProcessSuperMapping(){ public void linkWithSuperType(MappingModelCreationProcess creationProcess) { if ( getMappedSuperclass() != null ) { superMappingType = creationProcess.getEntityPersister( getMappedSuperclass() ); - final InFlightEntityMappingType inFlightEntityMappingType = (InFlightEntityMappingType) superMappingType; + final var inFlightEntityMappingType = (InFlightEntityMappingType) superMappingType; inFlightEntityMappingType.linkWithSubType(this, creationProcess); if ( subclassMappingTypes != null ) { subclassMappingTypes.values() @@ -5247,10 +5232,11 @@ protected EntityIdentifierMapping generateIdentifierMapping( final boolean encapsulated = !cidType.isEmbedded(); if ( encapsulated ) { // we have an `@EmbeddedId` - return MappingModelCreationHelper.buildEncapsulatedCompositeIdentifierMapping( + final var identifierProperty = bootEntityDescriptor.getIdentifierProperty(); + return buildEncapsulatedCompositeIdentifierMapping( this, - bootEntityDescriptor.getIdentifierProperty(), - bootEntityDescriptor.getIdentifierProperty().getName(), + identifierProperty, + identifierProperty.getName(), getTableName(), rootTableKeyColumnNames, cidType, @@ -5266,7 +5252,8 @@ protected EntityIdentifierMapping generateIdentifierMapping( final Integer arrayLength; final Integer precision; final Integer scale; - if ( bootEntityDescriptor.getIdentifier() == null ) { + final var identifier = bootEntityDescriptor.getIdentifier(); + if ( identifier == null ) { columnDefinition = null; length = null; arrayLength = null; @@ -5274,7 +5261,7 @@ protected EntityIdentifierMapping generateIdentifierMapping( scale = null; } else { - Column column = bootEntityDescriptor.getIdentifier().getColumns().get( 0 ); + final Column column = identifier.getColumns().get( 0 ); columnDefinition = column.getSqlType(); length = column.getLength(); arrayLength = column.getArrayLength(); @@ -5282,11 +5269,12 @@ protected EntityIdentifierMapping generateIdentifierMapping( scale = column.getScale(); } - final Value value = bootEntityDescriptor.getIdentifierProperty().getValue(); + final var identifierProperty = bootEntityDescriptor.getIdentifierProperty(); + final var value = identifierProperty.getValue(); return new BasicEntityIdentifierMappingImpl( this, templateInstanceCreator, - bootEntityDescriptor.getIdentifierProperty().getName(), + identifierProperty.getName(), getTableName(), rootTableKeyColumnNames[0], columnDefinition, @@ -5304,7 +5292,7 @@ protected EntityIdentifierMapping generateIdentifierMapping( protected EntityIdentifierMapping generateNonEncapsulatedCompositeIdentifierMapping( MappingModelCreationProcess creationProcess, PersistentClass bootEntityDescriptor) { - return MappingModelCreationHelper.buildNonEncapsulatedCompositeIdentifierMapping( + return buildNonEncapsulatedCompositeIdentifierMapping( this, getTableName(), getRootTableKeyColumnNames(), @@ -5323,12 +5311,12 @@ protected static EntityVersionMapping generateVersionMapping( Supplier templateInstanceCreator, PersistentClass bootModelRootEntityDescriptor, MappingModelCreationProcess creationProcess) { - final Property versionProperty = bootModelRootEntityDescriptor.getVersion(); - final BasicValue bootModelVersionValue = (BasicValue) versionProperty.getValue(); - final BasicValue.Resolution basicTypeResolution = bootModelVersionValue.resolve(); + final var versionProperty = bootModelRootEntityDescriptor.getVersion(); + final var bootModelVersionValue = (BasicValue) versionProperty.getValue(); + final var basicTypeResolution = bootModelVersionValue.resolve(); - final Column column = (Column) bootModelVersionValue.getColumn(); - final Dialect dialect = creationProcess.getCreationContext().getDialect(); + final var column = (Column) bootModelVersionValue.getColumn(); + final var dialect = creationProcess.getCreationContext().getDialect(); return new EntityVersionMappingImpl( bootModelRootEntityDescriptor.getRootClass(), @@ -5353,7 +5341,7 @@ protected AttributeMapping generateNonIdAttributeMapping( int stateArrayPosition, int fetchableIndex, MappingModelCreationProcess creationProcess) { - final RuntimeModelCreationContext creationContext = creationProcess.getCreationContext(); + final var creationContext = creationProcess.getCreationContext(); final String attrName = tupleAttrDefinition.getName(); final Type attrType = tupleAttrDefinition.getType(); @@ -5363,12 +5351,12 @@ protected AttributeMapping generateNonIdAttributeMapping( final String tableExpression = getTableName( getPropertyTableNumbers()[propertyIndex] ); final String[] attrColumnNames = getPropertyColumnNames( propertyIndex ); - final PropertyAccess propertyAccess = getRepresentationStrategy().resolvePropertyAccess( bootProperty ); + final var propertyAccess = getRepresentationStrategy().resolvePropertyAccess( bootProperty ); - final Value value = bootProperty.getValue(); + final var value = bootProperty.getValue(); if ( propertyIndex == getVersionProperty() ) { - Column column = value.getColumns().get( 0 ); - return MappingModelCreationHelper.buildBasicAttributeMapping( + final Column column = value.getColumns().get( 0 ); + return buildBasicAttributeMapping( attrName, getNavigableRole().append( bootProperty.getName() ), stateArrayPosition, @@ -5429,28 +5417,30 @@ protected AttributeMapping generateNonIdAttributeMapping( nullable = column.isNullable(); } else { - final BasicValue basicBootValue = (BasicValue) value; + final var basicBootValue = (BasicValue) value; if ( attrColumnNames[ 0 ] != null ) { attrColumnExpression = attrColumnNames[ 0 ]; isAttrColumnExpressionFormula = false; - final List selectables = basicBootValue.getSelectables(); + final var selectables = basicBootValue.getSelectables(); assert !selectables.isEmpty(); - final Selectable selectable = selectables.get(0); + final var selectable = selectables.get(0); + + final var dialect = creationContext.getDialect(); - assert attrColumnExpression.equals( selectable.getText( creationContext.getDialect() ) ); + assert attrColumnExpression.equals( selectable.getText( dialect ) ); customReadExpr = selectable.getTemplate( - creationContext.getDialect(), + dialect, creationContext.getTypeConfiguration() ); customWriteExpr = selectable.getWriteExpr( (JdbcMapping) attrType, - creationContext.getDialect(), + dialect, creationContext.getBootModel() ); - Column column = value.getColumns().get( 0 ); + final var column = value.getColumns().get( 0 ); columnDefinition = column.getSqlType(); length = column.getLength(); arrayLength = column.getArrayLength(); @@ -5459,7 +5449,7 @@ protected AttributeMapping generateNonIdAttributeMapping( scale = column.getScale(); nullable = column.isNullable(); isLob = column.isSqlTypeLob( creationContext.getMetadata() ); - MappingModelCreationHelper.resolveAggregateColumnBasicType( creationProcess, role, column ); + resolveAggregateColumnBasicType( creationProcess, role, column ); } else { final String[] attrColumnFormulaTemplate = propertyColumnFormulaTemplates[ propertyIndex ]; @@ -5478,7 +5468,7 @@ protected AttributeMapping generateNonIdAttributeMapping( } } - return MappingModelCreationHelper.buildBasicAttributeMapping( + return buildBasicAttributeMapping( attrName, role, stateArrayPosition, @@ -5512,8 +5502,9 @@ else if ( attrType instanceof AnyType anyType ) { creationContext.getTypeConfiguration().getJavaTypeRegistry() .getDescriptor( Object.class ); - final MutabilityPlan mutabilityPlan = new DiscriminatedAssociationAttributeMapping.MutabilityPlanImpl( anyType ); - final SimpleAttributeMetadata attributeMetadataAccess = new SimpleAttributeMetadata( + final MutabilityPlan mutabilityPlan = + new DiscriminatedAssociationAttributeMapping.MutabilityPlanImpl( anyType ); + final var attributeMetadataAccess = new SimpleAttributeMetadata( propertyAccess, mutabilityPlan, bootProperty.isOptional(), @@ -5539,11 +5530,13 @@ else if ( attrType instanceof AnyType anyType ) { ); } else if ( attrType instanceof CompositeType ) { - DependantValue dependantValue = null; - if ( bootProperty.getValue() instanceof DependantValue ) { - dependantValue = ( (DependantValue) bootProperty.getValue() ); + final DependantValue dependantValue; + if ( bootProperty.getValue() instanceof DependantValue depValue ) { + dependantValue = depValue; + } + else { + dependantValue = null; } - return buildEmbeddedAttributeMapping( attrName, stateArrayPosition, @@ -5724,20 +5717,20 @@ public AttributeMappingsList getAttributeMappings() { if ( attributeMappings == null ) { int sizeHint = declaredAttributeMappings.size(); sizeHint += (superMappingType == null ? 0 : superMappingType.getAttributeMappings().size() ); - ImmutableAttributeMappingList.Builder builder = new ImmutableAttributeMappingList.Builder( sizeHint ); + final var builder = new ImmutableAttributeMappingList.Builder( sizeHint ); if ( superMappingType != null ) { superMappingType.forEachAttributeMapping( builder::add ); } - for ( AttributeMapping am : declaredAttributeMappings.valueIterator() ) { + for ( var am : declaredAttributeMappings.valueIterator() ) { builder.add( am ); } attributeMappings = builder.build(); final Getter[] getters = new Getter[attributeMappings.size()]; final Setter[] setters = new Setter[attributeMappings.size()]; for ( int i = 0; i < attributeMappings.size(); i++ ) { - final PropertyAccess propertyAccess = attributeMappings.get( i ).getAttributeMetadata().getPropertyAccess(); + final var propertyAccess = attributeMappings.get( i ).getAttributeMetadata().getPropertyAccess(); getters[i] = propertyAccess.getGetter(); setters[i] = propertyAccess.getSetter(); } @@ -5756,7 +5749,7 @@ public AttributeMapping findDeclaredAttributeMapping(String name) { @Override public AttributeMapping findAttributeMapping(String name) { - final AttributeMapping declaredAttribute = declaredAttributeMappings.get( name ); + final var declaredAttribute = declaredAttributeMappings.get( name ); if ( declaredAttribute != null ) { return declaredAttribute; } @@ -5775,17 +5768,19 @@ public ModelPart findSubPart(String name, EntityMappingType treatTargetType) { return discriminatorMapping; } - final AttributeMapping declaredAttribute = declaredAttributeMappings.get( name ); + final var declaredAttribute = declaredAttributeMappings.get( name ); if ( declaredAttribute != null ) { return declaredAttribute; } if ( superMappingType != null ) { - final ModelPart superDefinedAttribute = superMappingType.findSubPart( name, superMappingType ); + final var superDefinedAttribute = + superMappingType.findSubPart( name, superMappingType ); if ( superDefinedAttribute != null ) { // Prefer the identifier mapping of the concrete class if ( superDefinedAttribute.isEntityIdentifierMapping() ) { - final ModelPart identifierModelPart = getIdentifierModelPart( name, treatTargetType ); + final var identifierModelPart = + getIdentifierModelPart( name, treatTargetType ); if ( identifierModelPart != null ) { return identifierModelPart; } @@ -5800,15 +5795,13 @@ public ModelPart findSubPart(String name, EntityMappingType treatTargetType) { } if ( subclassMappingTypes != null && !subclassMappingTypes.isEmpty() ) { - for ( EntityMappingType subMappingType : subclassMappingTypes.values() ) { - if ( ! treatTargetType.isTypeOrSuperType( subMappingType ) ) { - continue; - } - - final ModelPart subDefinedAttribute = subMappingType.findSubTypesSubPart( name, treatTargetType ); - - if ( subDefinedAttribute != null ) { - return subDefinedAttribute; + for ( var subMappingType : subclassMappingTypes.values() ) { + if ( treatTargetType.isTypeOrSuperType( subMappingType ) ) { + final var subDefinedAttribute = + subMappingType.findSubTypesSubPart( name, treatTargetType ); + if ( subDefinedAttribute != null ) { + return subDefinedAttribute; + } } } } @@ -5817,9 +5810,10 @@ public ModelPart findSubPart(String name, EntityMappingType treatTargetType) { if ( subclassMappingTypes != null && !subclassMappingTypes.isEmpty() ) { ModelPart attribute = null; for ( EntityMappingType subMappingType : subclassMappingTypes.values() ) { - final ModelPart subDefinedAttribute = subMappingType.findSubTypesSubPart( name, treatTargetType ); + final var subDefinedAttribute = + subMappingType.findSubTypesSubPart( name, treatTargetType ); if ( subDefinedAttribute != null ) { - if ( attribute != null && !MappingModelHelper.isCompatibleModelPart( attribute, subDefinedAttribute ) ) { + if ( attribute != null && !isCompatibleModelPart( attribute, subDefinedAttribute ) ) { throw new PathException( String.format( Locale.ROOT, @@ -5842,14 +5836,15 @@ public ModelPart findSubPart(String name, EntityMappingType treatTargetType) { } } - final ModelPart identifierModelPart = getIdentifierModelPart( name, treatTargetType ); + final var identifierModelPart = getIdentifierModelPart( name, treatTargetType ); if ( identifierModelPart != null ) { return identifierModelPart; } else { - for ( AttributeMapping attribute : declaredAttributeMappings.valueIterator() ) { - if ( attribute instanceof EmbeddableValuedModelPart part && attribute instanceof VirtualModelPart ) { - final ModelPart subPart = part.findSubPart( name, null ); + for ( var attribute : declaredAttributeMappings.valueIterator() ) { + if ( attribute instanceof EmbeddableValuedModelPart part + && attribute instanceof VirtualModelPart ) { + final var subPart = part.findSubPart( name, null ); if ( subPart != null ) { return subPart; } @@ -5861,14 +5856,15 @@ public ModelPart findSubPart(String name, EntityMappingType treatTargetType) { @Override public ModelPart findSubTypesSubPart(String name, EntityMappingType treatTargetType) { - final AttributeMapping declaredAttribute = declaredAttributeMappings.get( name ); + final var declaredAttribute = declaredAttributeMappings.get( name ); if ( declaredAttribute != null ) { return declaredAttribute; } else { if ( subclassMappingTypes != null && !subclassMappingTypes.isEmpty() ) { - for ( EntityMappingType subMappingType : subclassMappingTypes.values() ) { - final ModelPart subDefinedAttribute = subMappingType.findSubTypesSubPart( name, treatTargetType ); + for ( var subMappingType : subclassMappingTypes.values() ) { + final var subDefinedAttribute = + subMappingType.findSubTypesSubPart( name, treatTargetType ); if ( subDefinedAttribute != null ) { return subDefinedAttribute; } @@ -5879,9 +5875,9 @@ public ModelPart findSubTypesSubPart(String name, EntityMappingType treatTargetT } private ModelPart getIdentifierModelPart(String name, EntityMappingType treatTargetType) { - final EntityIdentifierMapping identifierMapping = getIdentifierMappingForJoin(); + final var identifierMapping = getIdentifierMappingForJoin(); if ( identifierMapping instanceof final NonAggregatedIdentifierMapping mapping ) { - final ModelPart subPart = mapping.findSubPart( name, treatTargetType ); + final var subPart = mapping.findSubPart( name, treatTargetType ); if ( subPart != null ) { return subPart; } @@ -5964,9 +5960,9 @@ public void visitFetchables(IndexedConsumer fetchableConsumer if ( treatTargetType.isTypeOrSuperType( this ) ) { if ( subclassMappingTypes != null ) { int offset = attributeMappings.size(); - for ( EntityMappingType subtype : subclassMappingTypes.values() ) { - final AttributeMappingsMap declaredAttributeMappings = subtype.getDeclaredAttributeMappings(); - for ( AttributeMapping declaredAttributeMapping : declaredAttributeMappings.valueIterator() ) { + for ( var subtype : subclassMappingTypes.values() ) { + final var declaredAttributeMappings = subtype.getDeclaredAttributeMappings(); + for ( var declaredAttributeMapping : declaredAttributeMappings.valueIterator() ) { fetchableConsumer.accept( offset++, declaredAttributeMapping ); } } @@ -5995,7 +5991,7 @@ public void visitSuperTypeAttributeMappings(Consumer a public int forEachSelectable(int offset, SelectableConsumer selectableConsumer) { int span = 0; for ( int i = 0; i < attributeMappings.size(); i++ ) { - final AttributeMapping attributeMapping = attributeMappings.get( i ); + final var attributeMapping = attributeMappings.get( i ); span += attributeMapping.forEachSelectable( span + offset, selectableConsumer ); } return span; @@ -6029,7 +6025,7 @@ public Object disassemble(Object value, SharedSessionContractImplementor session if ( value == null ) { return null; } - final EntityIdentifierMapping identifierMapping = getIdentifierMapping(); + final var identifierMapping = getIdentifierMapping(); final Object identifier = identifierMapping.getIdentifier( value ); return identifierMapping.disassemble( identifier, session ); } @@ -6054,7 +6050,7 @@ public int forEachJdbcValue( Y y, JdbcValuesBiConsumer consumer, SharedSessionContractImplementor session) { - final EntityIdentifierMapping identifierMapping = getIdentifierMapping(); + final var identifierMapping = getIdentifierMapping(); final Object identifier = value == null ? null : identifierMapping.disassemble( identifierMapping.getIdentifier( value ), session ); return identifierMapping.forEachDisassembledJdbcValue( identifier, offset, x, y, consumer, session ); @@ -6197,17 +6193,17 @@ public String[] getSubclassPropertyColumnAliases(String propertyName, String suf } private void internalInitSubclassPropertyAliasesMap(String path, List properties) { - for (Property property : properties) { + for ( var property : properties ) { final String name = path == null ? property.getName() : path + "." + property.getName(); if ( property.isComposite() ) { - final Component component = (Component) property.getValue(); + final var component = (Component) property.getValue(); internalInitSubclassPropertyAliasesMap( name, component.getProperties() ); } final String[] aliases = new String[property.getColumnSpan()]; int l = 0; - final Dialect dialect = getDialect(); - for ( Selectable selectable: property.getSelectables() ) { + final var dialect = getDialect(); + for ( var selectable: property.getSelectables() ) { aliases[l] = selectable.getAlias( dialect, property.getValue().getTable() ); l++; } @@ -6227,7 +6223,7 @@ protected String getSqlWhereStringTableExpression(){ @Override public boolean managesColumns(String[] columnNames) { - for (String columnName : columnNames) { + for ( String columnName : columnNames ) { if ( !writesToColumn( columnName ) ) { return false; } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java index 002fd126e1d1..204f6b9aa32a 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java @@ -7,7 +7,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Supplier; @@ -23,18 +22,10 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.DynamicFilterAliasGenerator; import org.hibernate.internal.FilterAliasGenerator; -import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.jdbc.Expectation; import org.hibernate.mapping.Column; -import org.hibernate.mapping.Join; -import org.hibernate.mapping.KeyValue; -import org.hibernate.mapping.MappedSuperclass; import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.mapping.Selectable; -import org.hibernate.mapping.Subclass; import org.hibernate.mapping.Table; -import org.hibernate.mapping.Value; import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityMappingType; @@ -54,17 +45,18 @@ 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.BasicTypeRegistry; import org.hibernate.type.CompositeType; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.Type; -import org.hibernate.type.spi.TypeConfiguration; import org.jboss.logging.Logger; import static java.util.Collections.emptyMap; +import static org.hibernate.internal.util.collections.ArrayHelper.contains; +import static org.hibernate.internal.util.collections.ArrayHelper.join; import static org.hibernate.internal.util.collections.ArrayHelper.reverseFirst; 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.linkedMapOfSize; @@ -161,18 +153,18 @@ public JoinedSubclassEntityPersister( final RuntimeModelCreationContext creationContext) throws HibernateException { super( persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, creationContext ); - final Dialect dialect = creationContext.getDialect(); - final TypeConfiguration typeConfiguration = creationContext.getTypeConfiguration(); - final BasicTypeRegistry basicTypeRegistry = typeConfiguration.getBasicTypeRegistry(); + final var dialect = creationContext.getDialect(); + final var typeConfiguration = creationContext.getTypeConfiguration(); + final var basicTypeRegistry = typeConfiguration.getBasicTypeRegistry(); // DISCRIMINATOR if ( persistentClass.isPolymorphic() ) { forceDiscriminator = persistentClass.isForceDiscriminator(); - final Value discriminatorMapping = persistentClass.getDiscriminator(); + final var discriminatorMapping = persistentClass.getDiscriminator(); if ( discriminatorMapping != null ) { log.tracef( "Encountered explicit discriminator mapping for joined inheritance" ); - final Selectable selectable = discriminatorMapping.getSelectables().get(0); + final var selectable = discriminatorMapping.getSelectables().get(0); if ( selectable instanceof Column column ) { explicitDiscriminatorColumnName = column.getQuotedName( dialect ); discriminatorAlias = column.getAlias( dialect, persistentClass.getRootTable() ); @@ -219,18 +211,18 @@ public JoinedSubclassEntityPersister( final ArrayList keyColumnReaders = new ArrayList<>(); final ArrayList keyColumnReaderTemplates = new ArrayList<>(); final ArrayList cascadeDeletes = new ArrayList<>(); - final List tableClosure = persistentClass.getTableClosure(); - final List keyClosure = persistentClass.getKeyClosure(); + final var tableClosure = persistentClass.getTableClosure(); + final var keyClosure = persistentClass.getKeyClosure(); for ( int i = 0; i < tableClosure.size() && i < keyClosure.size(); i++ ) { tableNames.add( determineTableName( tableClosure.get(i) ) ); - final KeyValue key = keyClosure.get(i); + final var key = keyClosure.get(i); final String[] keyCols = new String[idColumnSpan]; final String[] keyColReaders = new String[idColumnSpan]; final String[] keyColReaderTemplates = new String[idColumnSpan]; - final List columns = key.getColumns(); + final var columns = key.getColumns(); for ( int k = 0; k < idColumnSpan; k++ ) { - final Column column = columns.get(k); + final var column = columns.get(k); keyCols[k] = column.getQuotedName( dialect ); keyColReaders[k] = column.getReadExpr( dialect ); keyColReaderTemplates[k] = column.getTemplate( dialect, typeConfiguration ); @@ -249,24 +241,24 @@ public JoinedSubclassEntityPersister( isNullableTable = new boolean[tableSpan]; isInverseTable = new boolean[tableSpan]; - final List joinClosure = persistentClass.getJoinClosure(); + final var joinClosure = persistentClass.getJoinClosure(); for ( int i = 0; i < joinClosure.size(); i++ ) { - final Join join = joinClosure.get(i); + final var join = joinClosure.get(i); isNullableTable[i] = join.isOptional(); isInverseTable[i] = join.isInverse(); tableNames.add( determineTableName( join.getTable() ) ); - final KeyValue key = join.getKey(); + final var key = join.getKey(); final int joinIdColumnSpan = key.getColumnSpan(); final String[] keyCols = new String[joinIdColumnSpan]; final String[] keyColReaders = new String[joinIdColumnSpan]; final String[] keyColReaderTemplates = new String[joinIdColumnSpan]; - final List columns = key.getColumns(); + final var columns = key.getColumns(); for ( int k = 0; k < joinIdColumnSpan; k++ ) { - final Column column = columns.get(k); + final var column = columns.get(k); keyCols[k] = column.getQuotedName( dialect ); keyColReaders[k] = column.getReadExpr( dialect ); keyColReaderTemplates[k] = column.getTemplate( dialect, typeConfiguration ); @@ -282,20 +274,20 @@ public JoinedSubclassEntityPersister( naturalOrderTableKeyColumns = to2DStringArray( keyColumns ); final String[][] naturalOrderTableKeyColumnReaders = to2DStringArray( keyColumnReaders ); final String[][] naturalOrderTableKeyColumnReaderTemplates = to2DStringArray( keyColumnReaderTemplates ); - naturalOrderCascadeDeleteEnabled = ArrayHelper.toBooleanArray( cascadeDeletes ); + naturalOrderCascadeDeleteEnabled = toBooleanArray( cascadeDeletes ); final ArrayList subclassTableNames = new ArrayList<>(); final ArrayList isConcretes = new ArrayList<>(); final ArrayList isNullables = new ArrayList<>(); final ArrayList allKeyColumns = new ArrayList<>(); - for ( Table table : persistentClass.getSubclassTableClosure() ) { + for ( var table : persistentClass.getSubclassTableClosure() ) { isConcretes.add( persistentClass.isClassOrSuperclassTable( table ) ); isNullables.add( false ); final String tableName = determineTableName( table ); subclassTableNames.add( tableName ); final String[] key = new String[idColumnSpan]; - final List columns = table.getPrimaryKey().getColumnsInOriginalOrder(); + final var columns = table.getPrimaryKey().getColumnsInOriginalOrder(); for ( int k = 0; k < idColumnSpan; k++ ) { key[k] = columns.get(k).getQuotedName( dialect ); } @@ -303,14 +295,14 @@ public JoinedSubclassEntityPersister( } //Add joins - for ( Join join : persistentClass.getSubclassJoinClosure() ) { - final Table joinTable = join.getTable(); + for ( var join : persistentClass.getSubclassJoinClosure() ) { + final var joinTable = join.getTable(); isConcretes.add( persistentClass.isClassOrSuperclassTable( joinTable ) ); isNullables.add( join.isOptional() ); final String joinTableName = determineTableName( joinTable ); subclassTableNames.add( joinTableName ); final String[] key = new String[idColumnSpan]; - final List columns = joinTable.getPrimaryKey().getColumnsInOriginalOrder(); + final var columns = joinTable.getPrimaryKey().getColumnsInOriginalOrder(); for ( int k = 0; k < idColumnSpan; k++ ) { key[k] = columns.get(k).getQuotedName( dialect ); } @@ -319,8 +311,8 @@ public JoinedSubclassEntityPersister( final String[] naturalOrderSubclassTableNameClosure = toStringArray( subclassTableNames ); final String[][] naturalOrderSubclassTableKeyColumnClosure = to2DStringArray( allKeyColumns ); - isClassOrSuperclassTable = ArrayHelper.toBooleanArray( isConcretes ); - isNullableSubclassTable = ArrayHelper.toBooleanArray( isNullables ); + isClassOrSuperclassTable = toBooleanArray( isConcretes ); + isNullableSubclassTable = toBooleanArray( isNullables ); constraintOrderedTableNames = new String[naturalOrderSubclassTableNameClosure.length]; constraintOrderedKeyColumnNames = new String[naturalOrderSubclassTableNameClosure.length][]; @@ -345,7 +337,7 @@ public JoinedSubclassEntityPersister( subclassTableNameClosure = reverseFirst( naturalOrderSubclassTableNameClosure, coreTableSpan ); subclassTableKeyColumnClosure = reverseFirst( naturalOrderSubclassTableKeyColumnClosure, coreTableSpan ); - spaces = ArrayHelper.join( this.tableNames, toStringArray( persistentClass.getSynchronizedTables() ) ); + spaces = join( this.tableNames, toStringArray( persistentClass.getSynchronizedTables() ) ); // Custom sql customSQLInsert = new String[tableSpan]; @@ -386,7 +378,7 @@ public JoinedSubclassEntityPersister( } int j = coreTableSpan; - for ( Join join : persistentClass.getJoinClosure() ) { + for ( var join : persistentClass.getJoinClosure() ) { isInverseTable[j] = join.isInverse(); isNullableTable[j] = join.isOptional(); @@ -405,14 +397,16 @@ public JoinedSubclassEntityPersister( j++; } + final var sqlStringGenerationContext = creationContext.getSqlStringGenerationContext(); + // PROPERTIES final int hydrateSpan = getPropertySpan(); naturalOrderPropertyTableNumbers = new int[hydrateSpan]; - final List propertyClosure = persistentClass.getPropertyClosure(); + final var propertyClosure = persistentClass.getPropertyClosure(); for ( int i = 0; i < propertyClosure.size(); i++ ) { final String tableName = propertyClosure.get(i).getValue().getTable() - .getQualifiedName( creationContext.getSqlStringGenerationContext() ); + .getQualifiedName( sqlStringGenerationContext ); naturalOrderPropertyTableNumbers[i] = getTableId( tableName, naturalOrderTableNames ); } @@ -424,17 +418,16 @@ public JoinedSubclassEntityPersister( final ArrayList propTableNumbers = new ArrayList<>(); final ArrayList columns = new ArrayList<>(); - for ( Property property : persistentClass.getSubclassPropertyClosure() ) { + for ( var property : persistentClass.getSubclassPropertyClosure() ) { final String tableName = property.getValue().getTable(). - getQualifiedName( creationContext.getSqlStringGenerationContext() ); + getQualifiedName( sqlStringGenerationContext ); final Integer tableNumber = getTableId( tableName, subclassTableNameClosure ); final Integer naturalTableNumber = getTableId( tableName, naturalOrderSubclassTableNameClosure ); propTableNumbers.add( tableNumber ); - for ( Selectable selectable : property.getSelectables() ) { - if ( !selectable.isFormula() ) { + for ( var selectable : property.getSelectables() ) { + if ( selectable instanceof Column column ) { columnTableNumbers.add( naturalTableNumber ); - Column column = (Column) selectable; columns.add( column.getQuotedName( dialect ) ); } } @@ -462,24 +455,30 @@ public JoinedSubclassEntityPersister( discriminatorValuesByTableName = linkedMapOfSize( subclassSpan + 1 ); discriminatorColumnNameByTableName = linkedMapOfSize( subclassSpan + 1 ); - final Table table = persistentClass.getTable(); + final var table = persistentClass.getTable(); discriminatorValues = new String[subclassSpan]; discriminatorAbstract = new boolean[subclassSpan]; - initDiscriminatorProperties( dialect, subclassSpanMinusOne, table, discriminatorValue, isAbstract( persistentClass) ); + initDiscriminatorProperties( + dialect, + subclassSpanMinusOne, + table, + discriminatorValue, + isAbstract( persistentClass) + ); notNullColumnTableNumbers = new int[subclassSpan]; final int id = getTableId( - table.getQualifiedName( creationContext.getSqlStringGenerationContext() ), + table.getQualifiedName( sqlStringGenerationContext ), subclassTableNameClosure ); notNullColumnTableNumbers[subclassSpanMinusOne] = id; notNullColumnNames = new String[subclassSpan]; notNullColumnNames[subclassSpanMinusOne] = subclassTableKeyColumnClosure[id][0]; - final List subclasses = persistentClass.getSubclasses(); + final var subclasses = persistentClass.getSubclasses(); for ( int k = 0; k < subclasses.size(); k++ ) { - final Subclass subclass = subclasses.get(k); - final Table subclassTable = subclass.getTable(); + final var subclass = subclasses.get(k); + final var subclassTable = subclass.getTable(); if ( persistentClass.isPolymorphic() ) { final Object discriminatorValue = explicitDiscriminatorColumnName != null ? DiscriminatorHelper.getDiscriminatorValue( subclass ) @@ -490,7 +489,7 @@ public JoinedSubclassEntityPersister( initDiscriminatorProperties( dialect, k, subclassTable, discriminatorValue, isAbstract( subclass ) ); subclassesByDiscriminatorValue.put( discriminatorValue, subclass.getEntityName() ); final int tableId = getTableId( - subclassTable.getQualifiedName( creationContext.getSqlStringGenerationContext() ), + subclassTable.getQualifiedName( sqlStringGenerationContext ), subclassTableNameClosure ); notNullColumnTableNumbers[k] = tableId; @@ -501,7 +500,7 @@ public JoinedSubclassEntityPersister( subclassNamesBySubclassTable = buildSubclassNamesBySubclassTableMapping( persistentClass, - creationContext.getSqlStringGenerationContext() + sqlStringGenerationContext ); initSubclassPropertyAliasesMap( persistentClass ); @@ -574,10 +573,11 @@ private String[][] buildSubclassNamesBySubclassTableMapping( if ( numberOfSubclassTables == 0 ) { return new String[0][]; } - - final String[][] mapping = new String[numberOfSubclassTables][]; - processPersistentClassHierarchy( persistentClass, true, mapping, context ); - return mapping; + else { + final String[][] mapping = new String[numberOfSubclassTables][]; + processPersistentClassHierarchy( persistentClass, true, mapping, context ); + return mapping; + } } private Set processPersistentClassHierarchy( @@ -585,30 +585,22 @@ private Set processPersistentClassHierarchy( boolean isBase, String[][] mapping, SqlStringGenerationContext context) { - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // collect all the class names that indicate that the "main table" of the given PersistentClass should be - // included when one of the collected class names is used in TREAT + // collect all the class names that indicate that the "main table" + // of the given PersistentClass should be included when one of the + // collected class names is used in TREAT final Set classNames = new HashSet<>(); - - for ( Subclass subclass : persistentClass.getDirectSubclasses() ) { - final Set subclassSubclassNames = - processPersistentClassHierarchy( subclass, false, mapping, context ); - classNames.addAll( subclassSubclassNames ); + for ( var subclass : persistentClass.getDirectSubclasses() ) { + classNames.addAll( processPersistentClassHierarchy( subclass, false, mapping, context ) ); } - classNames.add( persistentClass.getEntityName() ); - if ( !isBase ) { - MappedSuperclass msc = persistentClass.getSuperMappedSuperclass(); - while ( msc != null ) { - classNames.add( msc.getMappedClass().getName() ); - msc = msc.getSuperMappedSuperclass(); + var mappedSuperclass = persistentClass.getSuperMappedSuperclass(); + while ( mappedSuperclass != null ) { + classNames.add( mappedSuperclass.getMappedClass().getName() ); + mappedSuperclass = mappedSuperclass.getSuperMappedSuperclass(); } - associateSubclassNamesToSubclassTableIndexes( persistentClass, classNames, mapping, context ); } - return classNames; } @@ -617,11 +609,9 @@ private void associateSubclassNamesToSubclassTableIndexes( Set classNames, String[][] mapping, SqlStringGenerationContext context) { - final String tableName = persistentClass.getTable().getQualifiedName( context ); associateSubclassNamesToSubclassTableIndex( tableName, classNames, mapping ); - - for ( Join join : persistentClass.getJoins() ) { + for ( var join : persistentClass.getJoins() ) { final String secondaryTableName = join.getTable().getQualifiedName( context ); associateSubclassNamesToSubclassTableIndex( secondaryTableName, classNames, mapping ); } @@ -679,7 +669,7 @@ protected void visitMutabilityOrderedTables(MutabilityOrderedTableConsumer consu consumer.consume( tableName, tableIndex, - () -> (columnConsumer) -> columnConsumer.accept( + () -> columnConsumer -> columnConsumer.accept( tableName, getIdentifierMapping(), naturalOrderTableKeyColumns[tableIndex] @@ -748,25 +738,28 @@ public String getDiscriminatorAlias() { @Override public void addDiscriminatorToInsertGroup(MutationGroupBuilder insertGroupBuilder) { if ( explicitDiscriminatorColumnName != null ) { - final TableInsertBuilder tableInsertBuilder = insertGroupBuilder.getTableDetailsBuilder( getRootTableName() ); - final String discriminatorValueToUse; - if ( discriminatorValue == NULL_DISCRIMINATOR ) { - discriminatorValueToUse = "null"; - } - else if ( discriminatorValue == NOT_NULL_DISCRIMINATOR ) { - discriminatorValueToUse = "not null"; - } - else { - discriminatorValueToUse = discriminatorSQLString; - } + final TableInsertBuilder tableInsertBuilder = + insertGroupBuilder.getTableDetailsBuilder( getRootTableName() ); tableInsertBuilder.addValueColumn( explicitDiscriminatorColumnName, - discriminatorValueToUse, + getDiscriminatorValueString(), getDiscriminatorMapping().getJdbcMapping() ); } } + private String getDiscriminatorValueString() { + if ( discriminatorValue == NULL_DISCRIMINATOR ) { + return "null"; + } + else if ( discriminatorValue == NOT_NULL_DISCRIMINATOR ) { + return "not null"; + } + else { + return discriminatorSQLString; + } + } + @Override public String[] getPropertySpaces() { return spaces; // don't need subclass tables, because they can't appear in conditions @@ -874,31 +867,29 @@ protected boolean isSubclassTableIndicatedByTreatAsDeclarations( if ( treatAsDeclarations == null || treatAsDeclarations.isEmpty() ) { return false; } - - final String[] inclusionSubclassNameClosure = getSubclassNameClosureBySubclassTable( subclassTableNumber ); - - // NOTE : we assume the entire hierarchy is joined-subclass here - for ( String subclassName : treatAsDeclarations ) { - for ( String inclusionSubclassName : inclusionSubclassNameClosure ) { - if ( inclusionSubclassName.equals( subclassName ) ) { - return true; + else { + final String[] inclusionSubclassNameClosure = + getSubclassNameClosureBySubclassTable( subclassTableNumber ); + // NOTE: we assume the entire hierarchy is joined-subclass here + for ( String subclassName : treatAsDeclarations ) { + for ( String inclusionSubclassName : inclusionSubclassNameClosure ) { + if ( inclusionSubclassName.equals( subclassName ) ) { + return true; + } } } + return false; } - - return false; } private String[] getSubclassNameClosureBySubclassTable(int subclassTableNumber) { final int index = subclassTableNumber - getTableSpan(); - if ( index >= subclassNamesBySubclassTable.length ) { throw new IllegalArgumentException( "Given subclass table number is outside expected range [" + (subclassNamesBySubclassTable.length -1) + "] as defined by subclassTableNameClosure/subclassClosure" ); } - return subclassNamesBySubclassTable[index]; } @@ -917,13 +908,14 @@ protected int determineTableNumberForColumn(String columnName) { // HHH-7630: In case the naturalOrder/identifier column is explicitly given in the ordering, check here. for ( int i = 0, max = naturalOrderTableKeyColumns.length; i < max; i++ ) { final String[] keyColumns = naturalOrderTableKeyColumns[i]; - if ( ArrayHelper.contains( keyColumns, columnName ) ) { + if ( contains( keyColumns, columnName ) ) { return naturalOrderPropertyTableNumbers[i]; } } - for (int i = 0, max = subclassColumnClosure.length; i < max; i++ ) { - final boolean quoted = subclassColumnClosure[i].startsWith( "\"" ) + for ( int i = 0, max = subclassColumnClosure.length; i < max; i++ ) { + final boolean quoted = + subclassColumnClosure[i].startsWith( "\"" ) && subclassColumnClosure[i].endsWith( "\"" ); if ( quoted ) { if ( subclassColumnClosure[i].equals( columnName ) ) { @@ -943,10 +935,10 @@ protected int determineTableNumberForColumn(String columnName) { @Override public Object forceVersionIncrement(Object id, Object currentVersion, SharedSessionContractImplementor session) { - if ( getSuperMappingType() != null ) { - return getSuperMappingType().getEntityPersister().forceVersionIncrement( id, currentVersion, session ); - } - return super.forceVersionIncrement( id, currentVersion, session ); + final var superMappingType = getSuperMappingType(); + return superMappingType != null + ? superMappingType.getEntityPersister().forceVersionIncrement( id, currentVersion, session ) + : super.forceVersionIncrement( id, currentVersion, session ); } @Override @@ -955,10 +947,10 @@ public Object forceVersionIncrement( Object currentVersion, boolean batching, SharedSessionContractImplementor session) throws HibernateException { - if ( getSuperMappingType() != null ) { - return getSuperMappingType().getEntityPersister().forceVersionIncrement( id, currentVersion, session ); - } - return super.forceVersionIncrement( id, currentVersion, batching, session ); + final var superMappingType = getSuperMappingType(); + return superMappingType != null + ? superMappingType.getEntityPersister().forceVersionIncrement( id, currentVersion, session ) + : super.forceVersionIncrement( id, currentVersion, batching, session ); } @Override @@ -971,8 +963,7 @@ protected EntityVersionMapping generateVersionMapping( } else { if ( getTableName().equals( getVersionedTableName() ) ) { - final int versionPropertyIndex = getVersionProperty(); - final String versionPropertyName = getPropertyNames()[versionPropertyIndex]; + final String versionPropertyName = getPropertyNames()[getVersionProperty()]; return creationProcess.processSubPart( versionPropertyName, (role, process) -> generateVersionMapping( @@ -993,40 +984,32 @@ else if ( getSuperMappingType() != null ) { @Override protected EntityIdentifierMapping generateIdentifierMapping( Supplier templateInstanceCreator, - PersistentClass bootEntityDescriptor, + PersistentClass persistentClass, MappingModelCreationProcess creationProcess) { final Type idType = getIdentifierType(); - - if ( idType instanceof CompositeType cidType ) { - - // NOTE: the term `isEmbedded` here uses Hibernate's older (pre-JPA) naming for its "non-aggregated" - // composite-id support. It unfortunately conflicts with the JPA usage of "embedded". Here we normalize - // the legacy naming to the more descriptive encapsulated versus non-encapsulated phrasing - - final boolean encapsulated = ! cidType.isEmbedded(); - if ( encapsulated ) { - // we have an `@EmbeddedId` - return buildEncapsulatedCompositeIdentifierMapping( - this, - bootEntityDescriptor.getIdentifierProperty(), - bootEntityDescriptor.getIdentifierProperty().getName(), - getTableName(), - tableKeyColumns[0], - cidType, - creationProcess - ); - } - - // otherwise we have a non-encapsulated composite-identifier - return generateNonEncapsulatedCompositeIdentifierMapping( creationProcess, bootEntityDescriptor ); + if ( idType instanceof CompositeType compositeIdType ) { + return compositeIdentifierMapping( persistentClass, creationProcess, compositeIdType ); + } + else if ( idType instanceof BasicType basicIdType ) { + return basicIdentifierMapping( templateInstanceCreator, persistentClass, creationProcess, basicIdType ); } + else { + throw new AssertionFailure( "Unrecognized id type" ); + } + } + private BasicEntityIdentifierMappingImpl basicIdentifierMapping( + Supplier templateInstanceCreator, + PersistentClass persistentClass, + MappingModelCreationProcess creationProcess, + BasicType idType) { + final var identifier = persistentClass.getIdentifier(); final String columnDefinition; final Long length; final Integer arrayLength; final Integer precision; final Integer scale; - if ( bootEntityDescriptor.getIdentifier() == null ) { + if ( identifier == null ) { columnDefinition = null; length = null; arrayLength = null; @@ -1034,18 +1017,19 @@ protected EntityIdentifierMapping generateIdentifierMapping( scale = null; } else { - final Column column = bootEntityDescriptor.getIdentifier().getColumns().get( 0 ); + final var column = identifier.getColumns().get( 0 ); columnDefinition = column.getSqlType(); length = column.getLength(); arrayLength = column.getArrayLength(); precision = column.getPrecision(); scale = column.getScale(); } - final Value value = bootEntityDescriptor.getIdentifierProperty().getValue(); + final var identifierProperty = persistentClass.getIdentifierProperty(); + final var value = identifierProperty.getValue(); return new BasicEntityIdentifierMappingImpl( this, templateInstanceCreator, - bootEntityDescriptor.getIdentifierProperty().getName(), + identifierProperty.getName(), getTableName(), tableKeyColumns[0][0], columnDefinition, @@ -1055,11 +1039,39 @@ protected EntityIdentifierMapping generateIdentifierMapping( scale, value.isColumnInsertable( 0 ), value.isColumnUpdateable( 0 ), - (BasicType) idType, + idType, creationProcess ); } + private EntityIdentifierMapping compositeIdentifierMapping( + PersistentClass persistentClass, + MappingModelCreationProcess creationProcess, + CompositeType compositeIdType) { + // NOTE: the term `isEmbedded` here uses Hibernate's older (pre-JPA) naming for its + // "non-aggregated" composite-id support. It unfortunately conflicts with the + // JPA usage of "embedded". Here we normalize the legacy naming to the more + // descriptive encapsulated versus non-encapsulated phrasing + final boolean encapsulated = !compositeIdType.isEmbedded(); + if ( encapsulated ) { + // we have an `@EmbeddedId` + final var identifierProperty = persistentClass.getIdentifierProperty(); + return buildEncapsulatedCompositeIdentifierMapping( + this, + identifierProperty, + identifierProperty.getName(), + getTableName(), + tableKeyColumns[0], + compositeIdType, + creationProcess + ); + } + else { + // otherwise we have a non-encapsulated composite-identifier + return generateNonEncapsulatedCompositeIdentifierMapping( creationProcess, persistentClass ); + } + } + @Override protected boolean isPhysicalDiscriminator() { return explicitDiscriminatorColumnName != null; @@ -1067,7 +1079,7 @@ protected boolean isPhysicalDiscriminator() { @Override protected EntityDiscriminatorMapping generateDiscriminatorMapping(PersistentClass bootEntityDescriptor) { - final EntityMappingType superMappingType = getSuperMappingType(); + final var superMappingType = getSuperMappingType(); if ( superMappingType != null ) { return superMappingType.getDiscriminatorMapping(); } @@ -1102,7 +1114,6 @@ protected EntityIdentifierMapping generateNonEncapsulatedCompositeIdentifierMapp MappingModelCreationProcess creationProcess, PersistentClass bootEntityDescriptor) { assert declaredAttributeMappings != null; - return buildNonEncapsulatedCompositeIdentifierMapping( this, getTableName(), @@ -1134,7 +1145,7 @@ public TableDetails getIdentifierTableDetails() { @Override public void pruneForSubclasses(TableGroup tableGroup, Map entityNameUses) { final Set retainedTableReferences = new HashSet<>( entityNameUses.size() ); - final MappingMetamodelImplementor metamodel = getFactory().getMappingMetamodel(); + final var metamodel = getFactory().getMappingMetamodel(); // We can only do this optimization if the table group reports canUseInnerJoins or isRealTableGroup, // because the switch for table reference joins to INNER must be cardinality preserving. // If canUseInnerJoins is true, this is trivially given, but also if the table group is real @@ -1142,61 +1153,21 @@ public void pruneForSubclasses(TableGroup tableGroup, Map final boolean innerJoinOptimization = tableGroup.canUseInnerJoins() || tableGroup.isRealTableGroup(); final Set tablesToInnerJoin = innerJoinOptimization ? new HashSet<>() : null; boolean needsTreatDiscriminator = false; - for ( Map.Entry entry : entityNameUses.entrySet() ) { - final EntityNameUse.UseKind useKind = entry.getValue().getKind(); - final JoinedSubclassEntityPersister persister = - (JoinedSubclassEntityPersister) metamodel.findEntityDescriptor( entry.getKey() ); + for ( var entry : entityNameUses.entrySet() ) { + final var useKind = entry.getValue().getKind(); + final var persister = (JoinedSubclassEntityPersister) metamodel.findEntityDescriptor( entry.getKey() ); // The following block tries to figure out what can be inner joined and which super class table joins can be omitted - if ( innerJoinOptimization && ( useKind == EntityNameUse.UseKind.TREAT || useKind == EntityNameUse.UseKind.FILTER ) ) { - final String[] subclassTableNames = persister.getSubclassTableNames(); - // Build the intersection of all tables names that are of the class or super class - // These are the tables that can be safely inner joined - final Set classOrSuperclassTables = new HashSet<>( subclassTableNames.length ); - for ( int i = 0; i < subclassTableNames.length; i++ ) { - if ( persister.isClassOrSuperclassTable[i] ) { - classOrSuperclassTables.add( subclassTableNames[i] ); - } - } - if ( tablesToInnerJoin.isEmpty() ) { - tablesToInnerJoin.addAll( classOrSuperclassTables ); - } - else { - tablesToInnerJoin.retainAll( classOrSuperclassTables ); - } - if ( useKind == EntityNameUse.UseKind.FILTER && explicitDiscriminatorColumnName == null ) { - // If there is no discriminator column, - // we must retain all joins to subclass tables to be able to discriminate the rows - for ( int i = 0; i < subclassTableNames.length; i++ ) { - if ( !persister.isClassOrSuperclassTable[i] ) { - final String subclassTableName = subclassTableNames[i]; - final TableReference mainTableReference = tableGroup.getTableReference( - null, - subclassTableName, - false - ); - if ( mainTableReference == null ) { - throw new UnknownTableReferenceException( - subclassTableName, - "Couldn't find table reference" - ); - } - retainedTableReferences.add( mainTableReference ); - } - } - } + if ( innerJoinOptimization ) { + optimizeInnerJoins( tableGroup, useKind, persister, tablesToInnerJoin, retainedTableReferences ); } final String tableName = persister.getTableName(); - final TableReference mainTableReference = tableGroup.getTableReference( - null, - tableName, - false - ); + final var mainTableReference = tableGroup.getTableReference( null, tableName, false ); if ( mainTableReference != null ) { retainedTableReferences.add( mainTableReference ); } final String sqlWhereStringTableExpression = persister.getSqlWhereStringTableExpression(); if ( sqlWhereStringTableExpression != null ) { - final TableReference tableReference = tableGroup.getTableReference( sqlWhereStringTableExpression ); + final var tableReference = tableGroup.getTableReference( sqlWhereStringTableExpression ); if ( tableReference != null ) { retainedTableReferences.add( tableReference ); } @@ -1219,13 +1190,14 @@ public void pruneForSubclasses(TableGroup tableGroup, Map } } - final List tableReferenceJoins = tableGroup.getTableReferenceJoins(); + final var tableReferenceJoins = tableGroup.getTableReferenceJoins(); if ( needsTreatDiscriminator ) { if ( tableReferenceJoins.isEmpty() ) { // We need to apply the discriminator predicate to the primary table reference itself - final String discriminatorPredicate = getPrunedDiscriminatorPredicate( entityNameUses, metamodel, "t" ); + final String discriminatorPredicate = + getPrunedDiscriminatorPredicate( entityNameUses, metamodel, "t" ); if ( discriminatorPredicate != null ) { - final NamedTableReference tableReference = (NamedTableReference) tableGroup.getPrimaryTableReference(); + final var tableReference = (NamedTableReference) tableGroup.getPrimaryTableReference(); tableReference.setPrunedTableExpression( "(select * from " + getRootTableName() + " t where " + discriminatorPredicate + ")" ); } } @@ -1239,7 +1211,7 @@ public void pruneForSubclasses(TableGroup tableGroup, Map ); int i = 0; for ( ; !applied && i < tableReferenceJoins.size(); i++ ) { - final TableReferenceJoin join = tableReferenceJoins.get( i ); + final var join = tableReferenceJoins.get( i ); applied = applyDiscriminatorPredicate( join, join.getJoinedTableReference(), entityNameUses, metamodel ); } assert applied : "Could not apply treat discriminator predicate to root table join"; @@ -1249,37 +1221,80 @@ public void pruneForSubclasses(TableGroup tableGroup, Map } } } - if ( tableReferenceJoins.isEmpty() ) { - return; + if ( !tableReferenceJoins.isEmpty() ) { + // The optimization is to remove all table reference joins that are not contained in the retainedTableReferences + // In addition, we switch from a possible LEFT join, to an INNER join for all tablesToInnerJoin + if ( innerJoinOptimization ) { + final var oldJoins = tableReferenceJoins.toArray( new TableReferenceJoin[0] ); + tableReferenceJoins.clear(); + for ( var oldJoin : oldJoins ) { + final var joinedTableReference = oldJoin.getJoinedTableReference(); + if ( retainedTableReferences.contains( joinedTableReference ) ) { + final var join = + oldJoin.getJoinType() != SqlAstJoinType.INNER + && tablesToInnerJoin.contains( joinedTableReference.getTableExpression() ) + ? new TableReferenceJoin( true, joinedTableReference, oldJoin.getPredicate() ) + : oldJoin; + tableReferenceJoins.add( join ); + } + else { + for ( int i = subclassCoreTableSpan; i < subclassTableNameClosure.length; i++ ) { + if ( joinedTableReference.getTableExpression().equals( subclassTableNameClosure[i] ) ) { + // Retain joins to secondary tables + tableReferenceJoins.add( oldJoin ); + break; + } + } + } + } + } + else { + tableReferenceJoins.removeIf( join -> !retainedTableReferences.contains( join.getJoinedTableReference() ) ); + } } - // The optimization is to remove all table reference joins that are not contained in the retainedTableReferences - // In addition, we switch from a possible LEFT join, to an INNER join for all tablesToInnerJoin - if ( innerJoinOptimization ) { - final TableReferenceJoin[] oldJoins = tableReferenceJoins.toArray( new TableReferenceJoin[0] ); - tableReferenceJoins.clear(); - for ( TableReferenceJoin oldJoin : oldJoins ) { - final NamedTableReference joinedTableReference = oldJoin.getJoinedTableReference(); - if ( retainedTableReferences.contains( joinedTableReference ) ) { - final TableReferenceJoin join = oldJoin.getJoinType() != SqlAstJoinType.INNER - && tablesToInnerJoin.contains( joinedTableReference.getTableExpression() ) - ? new TableReferenceJoin( true, joinedTableReference, oldJoin.getPredicate() ) - : oldJoin; - tableReferenceJoins.add( join ); + } + + private void optimizeInnerJoins( + TableGroup tableGroup, + EntityNameUse.UseKind useKind, + JoinedSubclassEntityPersister persister, + Set tablesToInnerJoin, + Set retainedTableReferences) { + if ( useKind == EntityNameUse.UseKind.TREAT || useKind == EntityNameUse.UseKind.FILTER ) { + final String[] subclassTableNames = persister.getSubclassTableNames(); + // Build the intersection of all tables names that are of the class or super class + // These are the tables that can be safely inner joined + final Set classOrSuperclassTables = new HashSet<>( subclassTableNames.length ); + for ( int i = 0; i < subclassTableNames.length; i++ ) { + if ( persister.isClassOrSuperclassTable[i] ) { + classOrSuperclassTables.add( subclassTableNames[i] ); } - else { - for ( int i = subclassCoreTableSpan; i < subclassTableNameClosure.length; i++ ) { - if ( joinedTableReference.getTableExpression().equals( subclassTableNameClosure[i] ) ) { - // Retain joins to secondary tables - tableReferenceJoins.add( oldJoin ); - break; + } + if ( tablesToInnerJoin.isEmpty() ) { + tablesToInnerJoin.addAll( classOrSuperclassTables ); + } + else { + tablesToInnerJoin.retainAll( classOrSuperclassTables ); + } + if ( useKind == EntityNameUse.UseKind.FILTER && explicitDiscriminatorColumnName == null ) { + // If there is no discriminator column, + // we must retain all joins to subclass tables to be able to discriminate the rows + for ( int i = 0; i < subclassTableNames.length; i++ ) { + if ( !persister.isClassOrSuperclassTable[i] ) { + final String subclassTableName = subclassTableNames[i]; + final var mainTableReference = + tableGroup.getTableReference( null, subclassTableName, false ); + if ( mainTableReference == null ) { + throw new UnknownTableReferenceException( + subclassTableName, + "Couldn't find table reference" + ); } + retainedTableReferences.add( mainTableReference ); } } } } - else { - tableReferenceJoins.removeIf( join -> !retainedTableReferences.contains( join.getJoinedTableReference() ) ); - } } @Override @@ -1297,11 +1312,8 @@ private boolean applyDiscriminatorPredicate( Map entityNameUses, MappingMetamodelImplementor metamodel) { if ( tableReference.getTableExpression().equals( getRootTableName() ) ) { - final String discriminatorPredicate = getPrunedDiscriminatorPredicate( - entityNameUses, - metamodel, - "t" - ); + final String discriminatorPredicate = + getPrunedDiscriminatorPredicate( entityNameUses, metamodel, "t" ); // null means we're filtering for all subtypes, so we don't need to apply a predicate if ( discriminatorPredicate != null ) { assert join.getJoinType() == SqlAstJoinType.INNER : "Found table reference join with root table of non-INNER type: " + join.getJoinType(); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java index 28cf8e4fcd48..ca5097a6abca 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java @@ -6,39 +6,32 @@ import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; +import org.hibernate.AssertionFailure; import org.hibernate.HibernateException; import org.hibernate.Internal; import org.hibernate.MappingException; import org.hibernate.Remove; import org.hibernate.cache.spi.access.EntityDataAccess; import org.hibernate.cache.spi.access.NaturalIdDataAccess; -import org.hibernate.dialect.Dialect; import org.hibernate.internal.DynamicFilterAliasGenerator; import org.hibernate.internal.FilterAliasGenerator; -import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.jdbc.Expectation; import org.hibernate.mapping.Column; import org.hibernate.mapping.Formula; -import org.hibernate.mapping.Join; import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.mapping.Selectable; -import org.hibernate.mapping.Subclass; -import org.hibernate.mapping.Table; -import org.hibernate.mapping.Value; +import org.hibernate.metamodel.MappingMetamodel; import org.hibernate.metamodel.mapping.TableDetails; -import org.hibernate.metamodel.spi.MappingMetamodelImplementor; import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.sql.ast.tree.from.NamedTableReference; import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.model.ast.builder.MutationGroupBuilder; import org.hibernate.sql.model.ast.builder.TableInsertBuilder; import org.hibernate.type.BasicType; -import org.hibernate.type.spi.TypeConfiguration; +import static org.hibernate.internal.util.collections.ArrayHelper.indexOf; +import static org.hibernate.internal.util.collections.ArrayHelper.join; 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; @@ -115,8 +108,8 @@ public SingleTableEntityPersister( final RuntimeModelCreationContext creationContext) throws HibernateException { super( persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, creationContext ); - final Dialect dialect = creationContext.getDialect(); - final TypeConfiguration typeConfiguration = creationContext.getTypeConfiguration(); + final var dialect = creationContext.getDialect(); + final var typeConfiguration = creationContext.getTypeConfiguration(); // CLASS + TABLE @@ -124,9 +117,7 @@ public SingleTableEntityPersister( // todo (6.2) : see note on AbstractEntityPersister#getTableName(int) qualifiedTableNames = new String[joinSpan]; - final Table table = persistentClass.getRootTable(); - final String rootTableName = determineTableName( table ); - qualifiedTableNames[0] = rootTableName; + qualifiedTableNames[0] = determineTableName( persistentClass.getRootTable() ); isInverseTable = new boolean[joinSpan]; isNullableTable = new boolean[joinSpan]; @@ -163,13 +154,13 @@ public SingleTableEntityPersister( // JOINS - final List joinClosure = persistentClass.getJoinClosure(); + final var joinClosure = persistentClass.getJoinClosure(); boolean hasDuplicateTableName = false; for ( int j = 1; j - 1 < joinClosure.size(); j++ ) { - Join join = joinClosure.get( j - 1 ); + final var join = joinClosure.get( j - 1 ); qualifiedTableNames[j] = determineTableName( join.getTable() ); hasDuplicateTableName = hasDuplicateTableName - || ArrayHelper.indexOf( qualifiedTableNames, j, qualifiedTableNames[j] ) != -1; + || indexOf( qualifiedTableNames, j, qualifiedTableNames[j] ) != -1; isInverseTable[j] = join.isInverse(); isNullableTable[j] = join.isOptional(); cascadeDeleteEnabled[j] = join.getKey().isCascadeDeleteEnabled() && dialect.supportsCascadeDelete(); @@ -188,7 +179,7 @@ public SingleTableEntityPersister( keyColumnNames[j] = new String[join.getKey().getColumnSpan()]; - final List columns = join.getKey().getColumns(); + final var columns = join.getKey().getColumns(); for ( int i = 0; i < columns.size(); i++ ) { keyColumnNames[j][i] = columns.get( i ).getQuotedName( dialect ); } @@ -202,7 +193,7 @@ public SingleTableEntityPersister( constraintOrderedKeyColumnNames[position] = keyColumnNames[i]; } - spaces = ArrayHelper.join( qualifiedTableNames, toStringArray( persistentClass.getSynchronizedTables() ) ); + spaces = join( qualifiedTableNames, toStringArray( persistentClass.getSynchronizedTables() ) ); final ArrayList subclassTables = new ArrayList<>(); final ArrayList joinKeyColumns = new ArrayList<>(); @@ -214,16 +205,15 @@ public SingleTableEntityPersister( isConcretes.add( true ); isClassOrSuperclassJoins.add( true ); isNullables.add( false ); - for ( Join join : persistentClass.getSubclassJoinClosure() ) { + for ( var join : persistentClass.getSubclassJoinClosure() ) { isConcretes.add( persistentClass.isClassOrSuperclassTable( join.getTable() ) ); isClassOrSuperclassJoins.add( persistentClass.isClassOrSuperclassJoin( join ) ); isNullables.add( join.isOptional() ); - final String joinTableName = determineTableName( join.getTable() ); - subclassTables.add( joinTableName ); + subclassTables.add( determineTableName( join.getTable() ) ); final String[] keyCols = new String[join.getKey().getColumnSpan()]; - final List columns = join.getKey().getColumns(); + final var columns = join.getKey().getColumns(); for ( int i = 0; i < columns.size(); i++ ) { keyCols[i] = columns.get( i ).getQuotedName( dialect ); } @@ -239,32 +229,33 @@ public SingleTableEntityPersister( // DISCRIMINATOR if ( persistentClass.isPolymorphic() ) { - final Value discriminator = persistentClass.getDiscriminator(); + final var discriminator = persistentClass.getDiscriminator(); if ( discriminator == null ) { throw new MappingException( "discriminator mapping required for single table polymorphic persistence" ); } forceDiscriminator = persistentClass.isForceDiscriminator(); - final Selectable selectable = discriminator.getSelectables().get( 0 ); + final var selectable = discriminator.getSelectables().get( 0 ); discriminatorType = DiscriminatorHelper.getDiscriminatorType( persistentClass ); discriminatorValue = DiscriminatorHelper.getDiscriminatorValue( persistentClass ); discriminatorSQLValue = DiscriminatorHelper.getDiscriminatorSQLValue( persistentClass, dialect ); discriminatorInsertable = isDiscriminatorInsertable( persistentClass ); - if ( discriminator.hasFormula() ) { - final Formula formula = (Formula) selectable; + if ( selectable instanceof Formula formula ) { discriminatorFormulaTemplate = formula.getTemplate( dialect, typeConfiguration ); discriminatorColumnName = null; discriminatorColumnReaders = null; discriminatorColumnReaderTemplate = null; discriminatorAlias = "clazz_"; } - else { - final Column column = (Column) selectable; + else if ( selectable instanceof Column column ) { discriminatorColumnName = column.getQuotedName( dialect ); discriminatorColumnReaders = column.getReadExpr( dialect ); discriminatorColumnReaderTemplate = column.getTemplate( dialect, typeConfiguration ); discriminatorAlias = column.getAlias( dialect, persistentClass.getRootTable() ); discriminatorFormulaTemplate = null; } + else { + throw new AssertionFailure( "Unrecognized selectable" ); + } } else { forceDiscriminator = false; @@ -282,7 +273,7 @@ public SingleTableEntityPersister( // PROPERTIES propertyTableNumbers = new int[getPropertySpan()]; - final List propertyClosure = persistentClass.getPropertyClosure(); + final var propertyClosure = persistentClass.getPropertyClosure(); for ( int k = 0; k < propertyClosure.size(); k++ ) { propertyTableNumbers[k] = persistentClass.getJoinNumber( propertyClosure.get( k ) ); } @@ -292,7 +283,7 @@ public SingleTableEntityPersister( final ArrayList propertyJoinNumbers = new ArrayList<>(); final Map subclassesByDiscriminatorValueLocal = new HashMap<>(); - for ( Property property : persistentClass.getSubclassPropertyClosure() ) { + for ( var property : persistentClass.getSubclassPropertyClosure() ) { propertyJoinNumbers.add( persistentClass.getJoinNumber( property ) ); } @@ -309,14 +300,13 @@ public SingleTableEntityPersister( ); // SUBCLASSES - final List subclasses = persistentClass.getSubclasses(); + final var subclasses = persistentClass.getSubclasses(); for ( int k = 0; k < subclasses.size(); k++ ) { - Subclass subclass = subclasses.get( k ); + final var subclass = subclasses.get( k ); subclassClosure[k] = subclass.getEntityName(); - Object subclassDiscriminatorValue = DiscriminatorHelper.getDiscriminatorValue( subclass ); addSubclassByDiscriminatorValue( subclassesByDiscriminatorValueLocal, - subclassDiscriminatorValue, + DiscriminatorHelper.getDiscriminatorValue( subclass ), subclass.getEntityName() ); } @@ -478,7 +468,8 @@ public int getTableSpan() { @Override public void addDiscriminatorToInsertGroup(MutationGroupBuilder insertGroupBuilder) { if ( discriminatorInsertable ) { - final TableInsertBuilder tableInsertBuilder = insertGroupBuilder.getTableDetailsBuilder( getRootTableName() ); + final TableInsertBuilder tableInsertBuilder = + insertGroupBuilder.getTableDetailsBuilder( getRootTableName() ); tableInsertBuilder.addValueColumn( discriminatorColumnName, discriminatorValue == NULL_DISCRIMINATOR ? NULL : discriminatorSQLValue, @@ -559,40 +550,39 @@ public FilterAliasGenerator getFilterAliasGenerator(String rootAlias) { @Override public void pruneForSubclasses(TableGroup tableGroup, Map entityNameUses) { - if ( !needsDiscriminator() && entityNameUses.isEmpty() ) { - return; - } - // The following optimization is to add the discriminator filter fragment for all treated entity names - final MappingMetamodelImplementor mappingMetamodel = getFactory().getMappingMetamodel(); - - boolean containsTreatUse = false; - for ( Map.Entry entry : entityNameUses.entrySet() ) { - final EntityNameUse.UseKind useKind = entry.getValue().getKind(); - if ( useKind == EntityNameUse.UseKind.PROJECTION || useKind == EntityNameUse.UseKind.EXPRESSION ) { - // We only care about treat and filter uses which allow to reduce the amount of rows to select - continue; + if ( needsDiscriminator() || !entityNameUses.isEmpty() ) {// The following optimization is to add the discriminator filter fragment for all treated entity names + final var mappingMetamodel = getFactory().getMappingMetamodel(); + if ( containsTreatUse( entityNameUses, mappingMetamodel ) ) { + final String discriminatorPredicate = + getPrunedDiscriminatorPredicate( entityNameUses, mappingMetamodel, "t" ); + if ( discriminatorPredicate != null ) { + final var tableReference = (NamedTableReference) tableGroup.getPrimaryTableReference(); + tableReference.setPrunedTableExpression( + "(select * from " + getTableName() + " t where " + discriminatorPredicate + ")" ); + } } - final EntityPersister persister = mappingMetamodel.getEntityDescriptor( entry.getKey() ); - // Filtering for abstract entities makes no sense, so ignore that - // Also, it makes no sense to filter for any of the super types, - // as the query will contain a filter for that already anyway - if ( useKind == EntityNameUse.UseKind.TREAT && !persister.isAbstract() - && ( getSuperMappingType() == null || !getSuperMappingType().isTypeOrSuperType( persister ) ) ) { - containsTreatUse = true; - break; - } - } - if ( !containsTreatUse ) { - // If we only have FILTER uses, we don't have to do anything here, - // because the BaseSqmToSqlAstConverter will already apply the type filter in the WHERE clause - return; + // Otherwise, if we only have FILTER uses, we don't have to do anything here because + // the BaseSqmToSqlAstConverter will already apply the type filter in the WHERE clause } + } - final String discriminatorPredicate = getPrunedDiscriminatorPredicate( entityNameUses, mappingMetamodel, "t" ); - if ( discriminatorPredicate != null ) { - final NamedTableReference tableReference = (NamedTableReference) tableGroup.getPrimaryTableReference(); - tableReference.setPrunedTableExpression( "(select * from " + getTableName() + " t where " + discriminatorPredicate + ")" ); + private boolean containsTreatUse(Map entityNameUses, MappingMetamodel metamodel) { + for ( var entry : entityNameUses.entrySet() ) { + // We only care about treat uses which allow to reduce the amount of rows to select + if ( entry.getValue().getKind() == EntityNameUse.UseKind.TREAT ) { + final var persister = metamodel.getEntityDescriptor( entry.getKey() ); + // Filtering for abstract entities makes no sense, so ignore that + if ( !persister.isAbstract() ) { + // Also, it makes no sense to filter for any of the super types, + // as the query will contain a filter for that already anyway + final var superMappingType = getSuperMappingType(); + if ( superMappingType == null || !getSuperMappingType().isTypeOrSuperType( persister ) ) { + return true; + } + } + } } + return false; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java index e357f9202903..d91ff9018c3d 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java @@ -7,11 +7,8 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; @@ -24,7 +21,6 @@ import org.hibernate.HibernateException; import org.hibernate.Internal; import org.hibernate.MappingException; -import org.hibernate.boot.Metadata; import org.hibernate.cache.spi.access.EntityDataAccess; import org.hibernate.cache.spi.access.NaturalIdDataAccess; import org.hibernate.dialect.Dialect; @@ -35,16 +31,12 @@ import org.hibernate.jdbc.Expectation; import org.hibernate.mapping.Column; import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Subclass; -import org.hibernate.mapping.Table; -import org.hibernate.metamodel.mapping.AttributeMappingsList; import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.SelectableConsumer; import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.metamodel.mapping.TableDetails; import org.hibernate.metamodel.mapping.internal.SqlTypedMappingImpl; -import org.hibernate.metamodel.spi.MappingMetamodelImplementor; import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.ast.spi.SqlAliasBase; @@ -58,6 +50,8 @@ import org.hibernate.type.BasicType; import org.hibernate.type.StandardBasicTypes; +import static java.util.Collections.addAll; +import static java.util.Collections.unmodifiableList; import static org.hibernate.internal.util.collections.ArrayHelper.to2DStringArray; import static org.hibernate.internal.util.collections.ArrayHelper.toStringArray; import static org.hibernate.jdbc.Expectations.createExpectation; @@ -100,7 +94,7 @@ public UnionSubclassEntityPersister( validateGenerator(); - final Dialect dialect = creationContext.getDialect(); + final var dialect = creationContext.getDialect(); // TABLE @@ -132,7 +126,7 @@ public UnionSubclassEntityPersister( // SUBCLASSES subclassByDiscriminatorValue.put( persistentClass.getSubclassId(), persistentClass.getEntityName() ); if ( persistentClass.isPolymorphic() ) { - for ( Subclass subclass : persistentClass.getSubclasses() ) { + for ( var subclass : persistentClass.getSubclasses() ) { subclassByDiscriminatorValue.put( subclass.getSubclassId(), subclass.getEntityName() ); } } @@ -141,32 +135,32 @@ public UnionSubclassEntityPersister( //TODO: I'm not sure, but perhaps we should exclude // abstract denormalized tables? - int spacesSize = 1 + persistentClass.getSynchronizedTables().size(); + final int spacesSize = 1 + persistentClass.getSynchronizedTables().size(); spaces = new String[spacesSize]; spaces[0] = tableName; - Iterator iter = persistentClass.getSynchronizedTables().iterator(); + final var iter = persistentClass.getSynchronizedTables().iterator(); for ( int i = 1; i < spacesSize; i++ ) { spaces[i] = iter.next(); } - HashSet subclassTables = new HashSet<>(); - for ( Table table : persistentClass.getSubclassTableClosure() ) { + final HashSet subclassTables = new HashSet<>(); + for ( var table : persistentClass.getSubclassTableClosure() ) { subclassTables.add( determineTableName( table ) ); } subclassSpaces = toStringArray( subclassTables ); - subquery = generateSubquery( persistentClass, creationContext.getMetadata() ); + subquery = generateSubquery( persistentClass ); final List tableExpressions = new ArrayList<>( subclassSpaces.length * 2 ); - Collections.addAll( tableExpressions, subclassSpaces ); + addAll( tableExpressions, subclassSpaces ); tableExpressions.add( subquery ); - PersistentClass parentPersistentClass = persistentClass.getSuperclass(); + var parentPersistentClass = persistentClass.getSuperclass(); while ( parentPersistentClass != null ) { - tableExpressions.add( generateSubquery( parentPersistentClass, creationContext.getMetadata() ) ); + tableExpressions.add( generateSubquery( parentPersistentClass ) ); parentPersistentClass = parentPersistentClass.getSuperclass(); } - for ( PersistentClass subPersistentClass : persistentClass.getSubclassClosure() ) { - if ( subPersistentClass.hasSubclasses() ) { - tableExpressions.add( generateSubquery( subPersistentClass, creationContext.getMetadata() ) ); + for ( var subclassPersistentClass : persistentClass.getSubclassClosure() ) { + if ( subclassPersistentClass.hasSubclasses() ) { + tableExpressions.add( generateSubquery( subclassPersistentClass ) ); } } subclassTableExpressions = toStringArray( tableExpressions ); @@ -175,7 +169,7 @@ public UnionSubclassEntityPersister( final int idColumnSpan = getIdentifierColumnSpan(); final ArrayList tableNames = new ArrayList<>(); final ArrayList keyColumns = new ArrayList<>(); - for ( Table table : persistentClass.getSubclassTableClosure() ) { + for ( var table : persistentClass.getSubclassTableClosure() ) { if ( !table.isAbstractUnionTable() ) { tableNames.add( determineTableName( table ) ); final String[] key = new String[idColumnSpan]; @@ -221,13 +215,16 @@ public boolean containsTableReference(String tableExpression) { public UnionTableReference createPrimaryTableReference( SqlAliasBase sqlAliasBase, SqlAstCreationState creationState) { - sqlAliasBase = SqlAliasBase.from( - sqlAliasBase, - null, - this, - creationState.getSqlAliasBaseGenerator() + return new UnionTableReference( + getTableName(), + subclassTableExpressions, + SqlAliasBase.from( + sqlAliasBase, + null, + this, + creationState.getSqlAliasBaseGenerator() + ).generateNewAlias() ); - return new UnionTableReference( getTableName(), subclassTableExpressions, sqlAliasBase.generateNewAlias() ); } @Override @@ -358,7 +355,7 @@ public boolean hasMultipleTables() { @Override public void pruneForSubclasses(TableGroup tableGroup, Map entityNameUses) { - final NamedTableReference tableReference = (NamedTableReference) tableGroup.getTableReference( getRootTableName() ); + final var tableReference = (NamedTableReference) tableGroup.getTableReference( getRootTableName() ); if ( tableReference == null ) { throw new UnknownTableReferenceException( getRootTableName(), "Couldn't find table reference" ); } @@ -411,67 +408,62 @@ protected int[] getPropertyTableNumbers() { return new int[getPropertySpan()]; } - protected String generateSubquery(PersistentClass model, Metadata mapping) { - - final Dialect dialect = getFactory().getJdbcServices().getDialect(); - + protected String generateSubquery(PersistentClass model) { + final var factory = getFactory(); + final var sqlStringGenerationContext = factory.getSqlStringGenerationContext(); if ( !model.hasSubclasses() ) { - return model.getTable().getQualifiedName( getFactory().getSqlStringGenerationContext() ); + return model.getTable().getQualifiedName( sqlStringGenerationContext ); } - - final Set columns = new LinkedHashSet<>(); - for ( Table table : model.getSubclassTableClosure() ) { - if ( !table.isAbstractUnionTable() ) { - columns.addAll( table.getColumns() ); + else { + final Set columns = new LinkedHashSet<>(); + for ( var table : model.getSubclassTableClosure() ) { + if ( !table.isAbstractUnionTable() ) { + columns.addAll( table.getColumns() ); + } } - } - - final StringBuilder subquery = new StringBuilder() - .append( "(" ); - - final List classes = new JoinedList<>( - List.of( model ), - Collections.unmodifiableList( model.getSubclasses() ) - ); - - for ( PersistentClass clazz : classes ) { - Table table = clazz.getTable(); - if ( !table.isAbstractUnionTable() ) { - //TODO: move to .sql package!! - if ( subquery.length() > 1 ) { - subquery.append( " union " ); - if ( dialect.supportsUnionAll() ) { - subquery.append( "all " ); + final var dialect = factory.getJdbcServices().getDialect(); + final var subquery = new StringBuilder().append( "(" ); + final var classes = + new JoinedList<>( List.of( model ), + unmodifiableList( model.getSubclasses() ) ); + for ( var persistentClass : classes ) { + final var table = persistentClass.getTable(); + if ( !table.isAbstractUnionTable() ) { + //TODO: move to .sql package!! + if ( subquery.length() > 1 ) { + subquery.append( " union " ); + if ( dialect.supportsUnionAll() ) { + subquery.append( "all " ); + } } - } - subquery.append( "select " ); - for ( Column col : columns ) { - if ( !table.containsColumn( col ) ) { - subquery.append( getSelectClauseNullString( col, dialect ) ) - .append(" as "); + subquery.append( "select " ); + for ( var column : columns ) { + if ( !table.containsColumn( column ) ) { + subquery.append( getSelectClauseNullString( column, dialect ) ) + .append( " as " ); + } + subquery.append( column.getQuotedName( dialect ) ) + .append( ", " ); } - subquery.append( col.getQuotedName( dialect ) ) - .append(", "); + subquery.append( persistentClass.getSubclassId() ) + .append( " as clazz_ from " ) + .append( table.getQualifiedName( sqlStringGenerationContext ) ); } - subquery.append( clazz.getSubclassId() ) - .append( " as clazz_ from " ) - .append( table.getQualifiedName( getFactory().getSqlStringGenerationContext() ) ); } + return subquery.append( ")" ).toString(); } - - return subquery.append( ")" ).toString(); } - private String getSelectClauseNullString(Column col, Dialect dialect) { + private String getSelectClauseNullString(Column column, Dialect dialect) { return dialect.getSelectClauseNullString( new SqlTypedMappingImpl( - col.getTypeName(), - col.getLength(), - col.getArrayLength(), - col.getPrecision(), - col.getScale(), - col.getTemporalPrecision(), - col.getType() + column.getTypeName(), + column.getLength(), + column.getArrayLength(), + column.getPrecision(), + column.getScale(), + column.getTemporalPrecision(), + column.getType() ), getFactory().getTypeConfiguration() ); @@ -482,15 +474,15 @@ protected String generateSubquery(Map entityNameUses) { return getTableName(); } - final Dialect dialect = getFactory().getJdbcServices().getDialect(); - final MappingMetamodelImplementor metamodel = getFactory().getMappingMetamodel(); + final var factory = getFactory(); + final var dialect = factory.getJdbcServices().getDialect(); + final var metamodel = factory.getMappingMetamodel(); // Collect all selectables of every entity subtype and group by selection expression as well as table name final LinkedHashMap> selectables = new LinkedHashMap<>(); final Set tablesToUnion = new HashSet<>( entityNameUses.size() ); // Check if there are filter uses and if so, we know the set of tables to union already - for ( Map.Entry entry : entityNameUses.entrySet() ) { - final UnionSubclassEntityPersister persister = - (UnionSubclassEntityPersister) metamodel.getEntityDescriptor( entry.getKey() ); + for ( var entry : entityNameUses.entrySet() ) { + final var persister = (UnionSubclassEntityPersister) metamodel.getEntityDescriptor( entry.getKey() ); if ( entry.getValue().getKind() == EntityNameUse.UseKind.FILTER && !persister.isAbstract() ) { tablesToUnion.add( persister.getRootTableName() ); } @@ -500,11 +492,10 @@ protected String generateSubquery(Map entityNameUses) { if ( tablesToUnion.isEmpty() ) { // If there are no filter uses, we try to find the most specific treat uses and union all their subclass tables - for ( Map.Entry entry : entityNameUses.entrySet() ) { + for ( var entry : entityNameUses.entrySet() ) { if ( entry.getValue().getKind() == EntityNameUse.UseKind.TREAT ) { // Collect all the real (non-abstract) table names - final UnionSubclassEntityPersister persister = - (UnionSubclassEntityPersister) metamodel.getEntityDescriptor( entry.getKey() ); + final var persister = (UnionSubclassEntityPersister) metamodel.getEntityDescriptor( entry.getKey() ); tablesToUnion.addAll( Arrays.asList( persister.getConstraintOrderedTableNameClosure() ) ); } } @@ -514,77 +505,70 @@ protected String generateSubquery(Map entityNameUses) { } } - // Create a union sub-query for the table names, like generateSubquery(PersistentClass model, Mapping mapping) - final StringBuilder buf = new StringBuilder( subquery.length() ).append( "(" ); - - final Collection subMappingTypes = getSubMappingTypes(); - final ArrayList subMappingTypesAndThis = new ArrayList<>( subMappingTypes.size() + 1 ); + // Create a union subquery for the table names, + // like generateSubquery(PersistentClass model) + final var unionSubquery = new StringBuilder( subquery.length() ).append( "(" ); + final var typeConfiguration = factory.getTypeConfiguration(); + final var subMappingTypes = getSubMappingTypes(); + final ArrayList subMappingTypesAndThis = + new ArrayList<>( subMappingTypes.size() + 1 ); subMappingTypesAndThis.add( this ); subMappingTypesAndThis.addAll( subMappingTypes ); - for ( EntityMappingType mappingType : subMappingTypesAndThis ) { - final EntityPersister persister = (EntityPersister) mappingType; - final String subclassTableName; - if ( mappingType.hasSubclasses() ) { - subclassTableName = persister.getRootTableName(); - } - else { - subclassTableName = persister.getTableName(); - } + for ( var mappingType : subMappingTypesAndThis ) { + final var persister = (EntityPersister) mappingType; + final String subclassTableName = + mappingType.hasSubclasses() + ? persister.getRootTableName() + : persister.getTableName(); if ( tablesToUnion.contains( subclassTableName ) ) { - if ( buf.length() > 1 ) { - buf.append(" union "); + if ( unionSubquery.length() > 1 ) { + unionSubquery.append(" union "); if ( dialect.supportsUnionAll() ) { - buf.append("all "); + unionSubquery.append("all "); } } - buf.append( "select " ); - for ( Map selectableMappings : selectables.values() ) { - SelectableMapping selectableMapping = selectableMappings.get( subclassTableName ); + unionSubquery.append( "select " ); + for ( var selectableMappings : selectables.values() ) { + var selectableMapping = selectableMappings.get( subclassTableName ); if ( selectableMapping == null ) { // If there is no selectable mapping for a table name, we render a null expression selectableMapping = selectableMappings.values().iterator().next(); - buf.append( dialect.getSelectClauseNullString( selectableMapping, getFactory().getTypeConfiguration() ) ) + unionSubquery.append( dialect.getSelectClauseNullString( selectableMapping, typeConfiguration ) ) .append( " as " ); } if ( selectableMapping.isFormula() ) { - buf.append( selectableMapping.getSelectableName() ); + unionSubquery.append( selectableMapping.getSelectableName() ); } else { - buf.append( selectableMapping.getSelectionExpression() ); + unionSubquery.append( selectableMapping.getSelectionExpression() ); } - buf.append( ", " ); + unionSubquery.append( ", " ); } - buf.append( persister.getDiscriminatorSQLValue() ) + unionSubquery.append( persister.getDiscriminatorSQLValue() ) .append( " as clazz_ from " ) .append( subclassTableName ); } } - return buf.append( ")" ).toString(); + return unionSubquery.append( ")" ).toString(); } private void collectSelectableOwners(LinkedHashMap> selectables) { if ( !isAbstract() ) { final SelectableConsumer selectableConsumer = (i, selectable) -> { - Map selectableMapping = selectables.computeIfAbsent( + var selectableMapping = selectables.computeIfAbsent( selectable.getSelectionExpression(), k -> new HashMap<>() ); - final String subclassTableName; - if ( hasSubclasses() ) { - subclassTableName = getRootTableName(); - } - else { - subclassTableName = getTableName(); - } + final String subclassTableName = hasSubclasses() ? getRootTableName() : getTableName(); selectableMapping.put( subclassTableName, selectable ); }; getIdentifierMapping().forEachSelectable( selectableConsumer ); - if ( getVersionMapping() != null ) { - getVersionMapping().forEachSelectable( selectableConsumer ); + final var versionMapping = getVersionMapping(); + if ( versionMapping != null ) { + versionMapping.forEachSelectable( selectableConsumer ); } - final AttributeMappingsList attributeMappings = getAttributeMappings(); - final int size = attributeMappings.size(); - for ( int i = 0; i < size; i++ ) { + final var attributeMappings = getAttributeMappings(); + for ( int i = 0, size = attributeMappings.size(); i < size; i++ ) { attributeMappings.get( i ).forEachSelectable( selectableConsumer ); } }