diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractCollectionBatchLoader.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractCollectionBatchLoader.java index 7ac72a5222b2..6e31b0eca5f5 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractCollectionBatchLoader.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractCollectionBatchLoader.java @@ -34,8 +34,6 @@ public abstract class AbstractCollectionBatchLoader implements CollectionBatchLo private final LoadQueryInfluencers influencers; private final SessionFactoryImplementor sessionFactory; - private final int keyJdbcCount; - final CollectionLoaderSingleKey singleKeyLoader; public AbstractCollectionBatchLoader( @@ -46,7 +44,6 @@ public AbstractCollectionBatchLoader( this.domainBatchSize = domainBatchSize; this.attributeMapping = attributeMapping; - this.keyJdbcCount = attributeMapping.getJdbcTypeCount(); this.sessionFactory = sessionFactory; this.influencers = influencers; @@ -54,7 +51,7 @@ public AbstractCollectionBatchLoader( } @Override - public int getDomainBatchSize() { + public final int getDomainBatchSize() { return domainBatchSize; } @@ -71,10 +68,6 @@ public SessionFactoryImplementor getSessionFactory() { return sessionFactory; } - public int getKeyJdbcCount() { - return keyJdbcCount; - } - abstract void initializeKeys(Object key, Object[] keysToInitialize, SharedSessionContractImplementor session); @Override @@ -85,69 +78,65 @@ public PersistentCollection load(Object key, SharedSessionContractImplementor } final Object[] keys = resolveKeysToInitialize( key, session ); - if ( hasSingleId( keys ) ) { return singleKeyLoader.load( key, session ); } - - initializeKeys( key, keys, session ); - - finishInitializingKeys( keys, session ); - - final CollectionKey collectionKey = new CollectionKey( getLoadable().getCollectionDescriptor(), key ); - return session.getPersistenceContext().getCollection( collectionKey ); + else { + initializeKeys( key, keys, session ); + finishInitializingKeys( keys, session ); + final CollectionKey collectionKey = new CollectionKey( getLoadable().getCollectionDescriptor(), key ); + return session.getPersistenceContext().getCollection( collectionKey ); + } } abstract void finishInitializingKeys(Object[] key, SharedSessionContractImplementor session); protected void finishInitializingKey(Object key, SharedSessionContractImplementor session) { - if ( key == null ) { - return; - } - - if ( MULTI_KEY_LOAD_LOGGER.isDebugEnabled() ) { - MULTI_KEY_LOAD_LOGGER.debugf( "Finishing initializing batch-fetched collection: %s.%s", - attributeMapping.getNavigableRole().getFullPath(), key ); - } + if ( key != null ) { + if ( MULTI_KEY_LOAD_LOGGER.isDebugEnabled() ) { + MULTI_KEY_LOAD_LOGGER.debugf( "Finishing initializing batch-fetched collection: %s.%s", + attributeMapping.getNavigableRole().getFullPath(), key ); + } - final PersistenceContext persistenceContext = session.getPersistenceContext(); - final CollectionKey collectionKey = new CollectionKey( getLoadable().getCollectionDescriptor(), key ); - final PersistentCollection collection = persistenceContext.getCollection( collectionKey ); - if ( !collection.wasInitialized() ) { - final CollectionEntry entry = persistenceContext.getCollectionEntry( collection ); - collection.initializeEmptyCollection( entry.getLoadedPersister() ); - ResultsHelper.finalizeCollectionLoading( - persistenceContext, - entry.getLoadedPersister(), - collection, - key, - true - ); + final PersistenceContext persistenceContext = session.getPersistenceContext(); + final CollectionKey collectionKey = new CollectionKey( getLoadable().getCollectionDescriptor(), key ); + final PersistentCollection collection = persistenceContext.getCollection( collectionKey ); + if ( !collection.wasInitialized() ) { + final CollectionEntry entry = persistenceContext.getCollectionEntry( collection ); + collection.initializeEmptyCollection( entry.getLoadedPersister() ); + ResultsHelper.finalizeCollectionLoading( + persistenceContext, + entry.getLoadedPersister(), + collection, + key, + true + ); + } } - } @AllowReflection Object[] resolveKeysToInitialize(Object keyBeingLoaded, SharedSessionContractImplementor session) { - final int length = getDomainBatchSize(); - final Object[] keysToInitialize = (Object[]) Array.newInstance( - getKeyType( getLoadable().getKeyDescriptor().getKeyPart() ), - length - ); + final Object[] keysToInitialize = createKeyArray(); session.getPersistenceContextInternal().getBatchFetchQueue() .collectBatchLoadableCollectionKeys( - length, + getDomainBatchSize(), (index, key) -> keysToInitialize[index] = key, keyBeingLoaded, getLoadable() ); // now trim down the array to the number of keys we found - return trimIdBatch( length, keysToInitialize ); + return trimIdBatch( getDomainBatchSize(), keysToInitialize ); + } + + private Object[] createKeyArray() { + final Class elementType = getKeyType( getLoadable().getKeyDescriptor().getKeyPart() ); + return (Object[]) Array.newInstance( elementType, getDomainBatchSize() ); } protected Class getKeyType(ValuedModelPart keyPart) { - if ( keyPart instanceof NonAggregatedIdentifierMapping ) { - final IdClassEmbeddable idClassEmbeddable = ( (NonAggregatedIdentifierMapping) keyPart ).getIdClassEmbeddable(); + if ( keyPart instanceof NonAggregatedIdentifierMapping nonAggregatedIdentifierMapping ) { + final IdClassEmbeddable idClassEmbeddable = nonAggregatedIdentifierMapping.getIdClassEmbeddable(); if ( idClassEmbeddable != null ) { return idClassEmbeddable.getMappedJavaType().getJavaTypeClass(); } @@ -155,5 +144,4 @@ protected Class getKeyType(ValuedModelPart keyPart) { return keyPart.getJavaType().getJavaTypeClass(); } - } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractEntityBatchLoader.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractEntityBatchLoader.java index 75c6f0b90e97..1c3a0d77d9c1 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractEntityBatchLoader.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractEntityBatchLoader.java @@ -49,7 +49,6 @@ public final T load( } final Object[] ids = resolveIdsToInitialize( id, session ); - return load( id, ids, hasSingleId( ids ), entityInstance, lockOptions, readOnly, session ); } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionBatchLoaderArrayParam.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionBatchLoaderArrayParam.java index e0882da3efd8..52a3ac6f2e3f 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionBatchLoaderArrayParam.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionBatchLoaderArrayParam.java @@ -20,6 +20,7 @@ import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.query.spi.QueryOptions; +import org.hibernate.sql.ast.SqlAstTranslatorFactory; import org.hibernate.sql.ast.tree.expression.JdbcParameter; import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.select.QuerySpec; @@ -34,6 +35,7 @@ import org.hibernate.sql.results.spi.ListResultsConsumer; import static org.hibernate.loader.ast.internal.MultiKeyLoadHelper.hasSingleId; +import static org.hibernate.loader.ast.internal.MultiKeyLoadHelper.resolveArrayJdbcMapping; import static org.hibernate.loader.ast.internal.MultiKeyLoadHelper.trimIdBatch; import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER; @@ -71,11 +73,7 @@ public CollectionBatchLoaderArrayParam( final Class jdbcJavaTypeClass = jdbcMapping.getJdbcJavaType().getJavaTypeClass(); keyDomainType = getKeyType( keyDescriptor.getKeyPart() ); - arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping( - jdbcMapping, - jdbcJavaTypeClass, - getSessionFactory() - ); + arrayJdbcMapping = resolveArrayJdbcMapping( jdbcMapping, jdbcJavaTypeClass, getSessionFactory() ); jdbcParameter = new JdbcParameterImpl( arrayJdbcMapping ); sqlSelect = LoaderSelectBuilder.createSelectBySingleArrayParameter( @@ -91,12 +89,16 @@ public CollectionBatchLoaderArrayParam( final TableGroup tableGroup = querySpec.getFromClause().getRoots().get( 0 ); attributeMapping.applySoftDeleteRestrictions( tableGroup, querySpec::applyPredicate ); - jdbcSelectOperation = getSessionFactory().getJdbcServices() - .getJdbcEnvironment() - .getSqlAstTranslatorFactory() - .buildSelectTranslator( getSessionFactory(), sqlSelect ) - .translate( JdbcParameterBindings.NO_BINDINGS, QueryOptions.NONE ); + jdbcSelectOperation = + getSqlAstTranslatorFactory() + .buildSelectTranslator( getSessionFactory(), sqlSelect ) + .translate( JdbcParameterBindings.NO_BINDINGS, QueryOptions.NONE ); + } + + private SqlAstTranslatorFactory getSqlAstTranslatorFactory() { + return getSessionFactory().getJdbcServices().getJdbcEnvironment().getSqlAstTranslatorFactory(); } + @Override public PersistentCollection load(Object keyBeingLoaded, SharedSessionContractImplementor session) { final ForeignKeyDescriptor keyDescriptor = getLoadable().getKeyDescriptor(); @@ -122,19 +124,11 @@ private PersistentCollection loadEmbeddable( ); } - final int length = getDomainBatchSize(); - final Object[] keysToInitialize = (Object[]) Array.newInstance( - jdbcParameter.getExpressionType() - .getSingleJdbcMapping() - .getJdbcJavaType() - .getJavaTypeClass() - .getComponentType(), - length - ); - final Object[] embeddedKeys = (Object[]) Array.newInstance( keyDomainType, length ); + final Object[] keysToInitialize = createKeyArray(); + final Object[] embeddedKeys = createEmbeddedKeyArray(); session.getPersistenceContextInternal().getBatchFetchQueue() .collectBatchLoadableCollectionKeys( - length, + getDomainBatchSize(), (index, key) -> keyDescriptor.forEachJdbcValue( key, (i, value, jdbcMapping) -> { keysToInitialize[index] = value; @@ -144,25 +138,33 @@ private PersistentCollection loadEmbeddable( keyBeingLoaded, getLoadable() ); - // now trim down the array to the number of keys we found - final Object[] keys = trimIdBatch( length, keysToInitialize ); + // now trim down the array to the number of keys we found + final Object[] keys = trimIdBatch( getDomainBatchSize(), keysToInitialize ); if ( hasSingleId( keys ) ) { return singleKeyLoader.load( keyBeingLoaded, session ); } - - initializeKeys( keyBeingLoaded, keys, session ); - - for ( Object initializedKey : embeddedKeys ) { - if ( initializedKey != null ) { - finishInitializingKey( initializedKey, session ); + else { + initializeKeys( keyBeingLoaded, keys, session ); + for ( Object initializedKey : embeddedKeys ) { + if ( initializedKey != null ) { + finishInitializingKey( initializedKey, session ); + } } + return session.getPersistenceContext() + .getCollection( new CollectionKey( getLoadable().getCollectionDescriptor(), keyBeingLoaded ) ); } - final CollectionKey collectionKey = new CollectionKey( - getLoadable().getCollectionDescriptor(), - keyBeingLoaded - ); - return session.getPersistenceContext().getCollection( collectionKey ); + } + + private Object[] createEmbeddedKeyArray() { + return (Object[]) Array.newInstance( keyDomainType, getDomainBatchSize() ); + } + + private Object[] createKeyArray() { + final Class elementType = + jdbcParameter.getExpressionType().getSingleJdbcMapping().getJdbcJavaType() + .getJavaTypeClass().getComponentType(); + return (Object[]) Array.newInstance( elementType, getDomainBatchSize() ); } @Override @@ -180,25 +182,21 @@ void initializeKeys(Object key, Object[] keysToInitialize, SharedSessionContract assert jdbcParameter != null; final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl(1); - jdbcParameterBindings.addBinding( - jdbcParameter, - new JdbcParameterBindingImpl( arrayJdbcMapping, keysToInitialize ) - ); - - final SubselectFetch.RegistrationHandler subSelectFetchableKeysHandler = SubselectFetch.createRegistrationHandler( - session.getPersistenceContext().getBatchFetchQueue(), - sqlSelect, - JdbcParametersList.singleton( jdbcParameter ), - jdbcParameterBindings - ); + jdbcParameterBindings.addBinding( jdbcParameter, + new JdbcParameterBindingImpl( arrayJdbcMapping, keysToInitialize ) ); + + final SubselectFetch.RegistrationHandler subSelectFetchableKeysHandler = + SubselectFetch.createRegistrationHandler( + session.getPersistenceContext().getBatchFetchQueue(), + sqlSelect, + JdbcParametersList.singleton( jdbcParameter ), + jdbcParameterBindings + ); session.getJdbcServices().getJdbcSelectExecutor().list( jdbcSelectOperation, jdbcParameterBindings, - new ExecutionContextWithSubselectFetchHandler( - session, - subSelectFetchableKeysHandler - ), + new ExecutionContextWithSubselectFetchHandler( session, subSelectFetchableKeysHandler ), RowTransformerStandardImpl.instance(), ListResultsConsumer.UniqueSemantic.FILTER ); @@ -215,24 +213,28 @@ void finishInitializingKeys(Object[] keys, SharedSessionContractImplementor sess @AllowReflection Object[] resolveKeysToInitialize(Object keyBeingLoaded, SharedSessionContractImplementor session) { final ForeignKeyDescriptor keyDescriptor = getLoadable().getKeyDescriptor(); - if( keyDescriptor.isEmbedded()){ + if ( keyDescriptor.isEmbedded() ) { assert keyDescriptor.getJdbcTypeCount() == 1; - final int length = getDomainBatchSize(); - final Object[] keysToInitialize = (Object[]) Array.newInstance( keyDescriptor.getSingleJdbcMapping().getJdbcJavaType().getJavaTypeClass(), length ); + final Object[] keysToInitialize = (Object[]) createForeignKeyArray( keyDescriptor ); session.getPersistenceContextInternal().getBatchFetchQueue() .collectBatchLoadableCollectionKeys( - length, + getDomainBatchSize(), (index, key) -> - keyDescriptor.forEachJdbcValue( key, (i, value, jdbcMapping) -> { - keysToInitialize[index] = value; - }, session ) - , + keyDescriptor.forEachJdbcValue( key, (i, value, jdbcMapping) -> + keysToInitialize[index] = value, session ), keyBeingLoaded, getLoadable() ); // now trim down the array to the number of keys we found - return trimIdBatch( length, keysToInitialize ); + return trimIdBatch( getDomainBatchSize(), keysToInitialize ); } - return super.resolveKeysToInitialize( keyBeingLoaded, session ); + else { + return super.resolveKeysToInitialize( keyBeingLoaded, session ); + } + } + + private Object createForeignKeyArray(ForeignKeyDescriptor keyDescriptor) { + final Class elementType = keyDescriptor.getSingleJdbcMapping().getJdbcJavaType().getJavaTypeClass(); + return Array.newInstance( elementType, getDomainBatchSize() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionBatchLoaderInPredicate.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionBatchLoaderInPredicate.java index 1858556c4f6e..1f3c67268c10 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionBatchLoaderInPredicate.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionBatchLoaderInPredicate.java @@ -11,6 +11,7 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SubselectFetch; import org.hibernate.loader.ast.spi.CollectionBatchLoader; +import org.hibernate.loader.ast.spi.MultiKeyLoadSizingStrategy; import org.hibernate.loader.ast.spi.SqlArrayMultiKeyLoader; import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.query.spi.QueryOptions; @@ -46,9 +47,7 @@ public CollectionBatchLoaderInPredicate( super( domainBatchSize, influencers, attributeMapping, sessionFactory ); keyColumnCount = attributeMapping.getKeyDescriptor().getJdbcTypeCount(); - sqlBatchSize = sessionFactory.getJdbcServices() - .getDialect() - .getBatchLoadSizingStrategy() + sqlBatchSize = getBatchLoadSizingStrategy( sessionFactory ) .determineOptimalBatchLoadSize( keyColumnCount, domainBatchSize, false ); if ( MULTI_KEY_LOAD_LOGGER.isDebugEnabled() ) { MULTI_KEY_LOAD_LOGGER.debugf( @@ -86,6 +85,10 @@ public CollectionBatchLoaderInPredicate( .translate( JdbcParameterBindings.NO_BINDINGS, QueryOptions.NONE ); } + private static MultiKeyLoadSizingStrategy getBatchLoadSizingStrategy(SessionFactoryImplementor sessionFactory) { + return sessionFactory.getJdbcServices().getDialect().getBatchLoadSizingStrategy(); + } + @Override void initializeKeys(Object key, Object[] keysToInitialize, SharedSessionContractImplementor session) { final boolean loggerDebugEnabled = MULTI_KEY_LOAD_LOGGER.isDebugEnabled(); @@ -114,12 +117,13 @@ void initializeKeys(Object key, Object[] keysToInitialize, SharedSessionContract countIds( keysToInitialize ), (jdbcParameterBindings, session1) -> { // Create a RegistrationHandler for handling any subselect fetches we encounter handling this chunk - final SubselectFetch.RegistrationHandler registrationHandler = SubselectFetch.createRegistrationHandler( - batchFetchQueue, - sqlAst, - jdbcParameters, - jdbcParameterBindings - ); + final SubselectFetch.RegistrationHandler registrationHandler = + SubselectFetch.createRegistrationHandler( + batchFetchQueue, + sqlAst, + jdbcParameters, + jdbcParameterBindings + ); return new ExecutionContextWithSubselectFetchHandler( session, registrationHandler ); }, (key1, relativePosition, absolutePosition) -> { diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionElementLoaderByIndex.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionElementLoaderByIndex.java index b15f5a380e55..2fd5b664068b 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionElementLoaderByIndex.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CollectionElementLoaderByIndex.java @@ -67,12 +67,12 @@ public CollectionElementLoaderByIndex( final ForeignKeyDescriptor keyDescriptor = attributeMapping.getKeyDescriptor(); final CollectionPart indexDescriptor = attributeMapping.getIndexDescriptor(); - List restrictedParts = new ArrayList<>(); + final List restrictedParts = new ArrayList<>(); restrictedParts.add( keyDescriptor ); - if ( indexDescriptor instanceof EntityCollectionPart ) { - EntityIdentifierMapping identifierMapping = ( (EntityCollectionPart) indexDescriptor ).getEntityMappingType() - .getIdentifierMapping(); + if ( indexDescriptor instanceof EntityCollectionPart entityCollectionPart ) { + final EntityIdentifierMapping identifierMapping = + entityCollectionPart.getEntityMappingType().getIdentifierMapping(); restrictedParts.add( identifierMapping ); this.keyJdbcCount = keyDescriptor.getJdbcTypeCount() + identifierMapping.getJdbcTypeCount(); @@ -83,7 +83,7 @@ public CollectionElementLoaderByIndex( indexDescriptor.getJdbcTypeCount(); } - List partsToSelect = new ArrayList<>(); + final List partsToSelect = new ArrayList<>(); partsToSelect.add( attributeMapping.getElementDescriptor() ); final JdbcParametersList.Builder jdbcParametersBuilder = JdbcParametersList.newBuilder( keyJdbcCount ); @@ -143,7 +143,7 @@ public Object load(Object key, Object index, SharedSessionContractImplementor se final JdbcOperationQuerySelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory, sqlAst ) .translate( jdbcParameterBindings, QueryOptions.NONE ); - List list = jdbcServices.getJdbcSelectExecutor().list( + final List list = jdbcServices.getJdbcSelectExecutor().list( jdbcSelect, jdbcParameterBindings, new BaseExecutionContext( session ), @@ -170,9 +170,6 @@ public Object load(Object key, Object index, SharedSessionContractImplementor se * @return The appropriately incremented base */ protected Object incrementIndexByBase(Object index) { - if ( baseIndex > 0 ) { - return (Integer) index + baseIndex; - } - return index; + return baseIndex > 0 ? (Integer) index + baseIndex : index; } } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaType.java index 4e1095b65c02..4c3ffad1640c 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JavaType.java @@ -113,12 +113,9 @@ default MutabilityPlan getMutabilityPlan() { } default T getReplacement(T original, T target, SharedSessionContractImplementor session) { - if ( !getMutabilityPlan().isMutable() || target != null && areEqual( original, target ) ) { - return original; - } - else { - return getMutabilityPlan().deepCopy( original ); - } + return !getMutabilityPlan().isMutable() || target != null && areEqual( original, target ) + ? original + : getMutabilityPlan().deepCopy( original ); } /**