From da22678c744970831dfbfba6dd9677cedf0f2111 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Tue, 28 May 2024 14:38:32 +0200 Subject: [PATCH] HHH-18154 Implement caching for assemblers and initializers * Make initializers stateless and have separate data classes stored in the RowProcessingState * Defer determination whether batching should apply and which lock mode should be used until startLoading * Inline EntityEntry to EntityHolder to avoid map lookup --- hibernate-core/hibernate-core.gradle | 4 + .../internal/AbstractEntityInsertAction.java | 9 +- .../BytecodeEnhancementMetadataPojoImpl.java | 6 +- .../spi/CollectionInitializerProducer.java | 61 +- .../internal/StatefulPersistenceContext.java | 163 +-- .../hibernate/engine/spi/EntityHolder.java | 8 +- .../org/hibernate/engine/spi/EntityKey.java | 2 +- .../engine/spi/PersistenceContext.java | 5 +- .../hibernate/engine/spi/SubselectFetch.java | 2 +- .../internal/AbstractSaveEventListener.java | 3 + .../internal/DefaultEvictEventListener.java | 2 +- .../internal/DefaultRefreshEventListener.java | 4 +- .../internal/GeneratedValuesHelper.java | 5 +- .../internal/AbstractScrollableResults.java | 2 +- .../FetchingScrollableResultsImpl.java | 6 +- .../internal/ScrollableResultsImpl.java | 2 +- .../ast/internal/CacheEntityLoaderHelper.java | 11 +- .../internal/CompoundNaturalIdMapping.java | 30 +- .../internal/ToOneAttributeMapping.java | 8 - .../query/results/JdbcValuesMappingImpl.java | 67 +- .../results/ResultSetMappingSqlSelection.java | 11 - .../results/complete/EntityResultImpl.java | 45 +- ...SelfRenderingFunctionSqlAstExpression.java | 13 - .../DiscriminatorPathInterpretation.java | 13 - .../sqm/sql/internal/SqmMapEntryResult.java | 70 +- .../result/internal/OutputsImpl.java | 21 +- .../sql/ast/spi/SqlSelectionProducer.java | 15 - .../sql/ast/tree/expression/Expression.java | 24 - .../ast/tree/from/DelegatingTableGroup.java | 14 - .../exec/internal/AbstractJdbcParameter.java | 17 - .../JdbcSelectExecutorStandardImpl.java | 15 +- .../results/graph/AssemblerCreationState.java | 16 +- .../sql/results/graph/DomainResult.java | 13 +- .../results/graph/DomainResultAssembler.java | 15 +- .../hibernate/sql/results/graph/Fetch.java | 15 +- .../sql/results/graph/FetchParent.java | 2 +- .../sql/results/graph/FetchParentAccess.java | 89 -- .../sql/results/graph/Initializer.java | 116 +-- .../sql/results/graph/InitializerData.java | 41 + .../sql/results/graph/InitializerParent.java | 2 +- .../results/graph/InitializerProducer.java | 4 +- .../UnfetchedBasicPartResultAssembler.java | 4 +- .../graph/UnfetchedResultAssembler.java | 4 +- .../sql/results/graph/basic/BasicFetch.java | 19 +- .../sql/results/graph/basic/BasicResult.java | 10 +- .../graph/basic/BasicResultAssembler.java | 7 +- .../collection/CollectionInitializer.java | 20 +- .../collection/LoadingCollectionEntry.java | 2 +- .../AbstractCollectionInitializer.java | 226 ++--- ...bstractImmediateCollectionInitializer.java | 404 +++----- .../collection/internal/ArrayInitializer.java | 79 +- .../internal/ArrayInitializerProducer.java | 18 +- .../collection/internal/BagInitializer.java | 69 +- .../internal/BagInitializerProducer.java | 18 +- .../internal/CollectionAssembler.java | 18 +- .../internal/CollectionDomainResult.java | 14 +- .../collection/internal/CollectionFetch.java | 14 +- .../internal/DelayedCollectionFetch.java | 12 +- .../DelayedCollectionInitializer.java | 26 +- .../internal/EagerCollectionFetch.java | 2 +- .../collection/internal/ListInitializer.java | 67 +- .../internal/ListInitializerProducer.java | 18 +- .../collection/internal/MapInitializer.java | 81 +- .../internal/MapInitializerProducer.java | 18 +- .../internal/SelectEagerCollectionFetch.java | 2 +- .../SelectEagerCollectionInitializer.java | 38 +- .../collection/internal/SetInitializer.java | 65 +- .../internal/SetInitializerProducer.java | 18 +- .../UnfetchedCollectionAssembler.java | 4 +- .../embeddable/EmbeddableInitializer.java | 30 +- .../AggregateEmbeddableFetchImpl.java | 16 +- .../AggregateEmbeddableInitializer.java | 53 - .../AggregateEmbeddableInitializerImpl.java | 44 +- .../AggregateEmbeddableResultImpl.java | 16 +- .../internal/EmbeddableAssembler.java | 17 +- .../EmbeddableExpressionResultImpl.java | 16 +- .../internal/EmbeddableFetchImpl.java | 17 +- .../EmbeddableForeignKeyResultImpl.java | 16 +- .../internal/EmbeddableInitializerImpl.java | 299 +++--- .../internal/EmbeddableResultImpl.java | 16 +- .../internal/NestedRowProcessingState.java | 33 +- .../NonAggregatedIdentifierMappingFetch.java | 2 +- ...ggregatedIdentifierMappingInitializer.java | 205 ++-- .../NonAggregatedIdentifierMappingResult.java | 4 +- .../graph/entity/EntityInitializer.java | 66 +- .../graph/entity/LoadingEntityEntry.java | 64 -- ...ractBatchEntitySelectFetchInitializer.java | 285 +++--- .../AbstractNonJoinedEntityFetch.java | 20 +- ...nsideEmbeddableSelectFetchInitializer.java | 171 +--- .../BatchEntitySelectFetchInitializer.java | 90 +- ...nitializeEntitySelectFetchInitializer.java | 76 +- .../internal/DiscriminatedEntityFetch.java | 16 +- .../DiscriminatedEntityInitializer.java | 231 ++--- .../internal/DiscriminatedEntityResult.java | 16 +- .../entity/internal/EntityAssembler.java | 19 +- .../internal/EntityDelayedFetchImpl.java | 10 +- .../EntityDelayedFetchInitializer.java | 190 ++-- .../internal/EntityFetchJoinedImpl.java | 45 +- .../internal/EntityFetchSelectImpl.java | 2 +- .../internal/EntityInitializerImpl.java | 940 +++++++++--------- .../entity/internal/EntityResultImpl.java | 21 +- ...titySelectFetchByUniqueKeyInitializer.java | 54 +- .../EntitySelectFetchInitializer.java | 226 ++--- .../EntitySelectFetchInitializerBuilder.java | 59 +- .../internal/ArgumentDomainResult.java | 10 +- .../internal/ArgumentReader.java | 14 +- ...InstantiationAssemblerConstructorImpl.java | 8 +- ...icInstantiationAssemblerInjectionImpl.java | 17 +- ...DynamicInstantiationAssemblerListImpl.java | 8 +- .../DynamicInstantiationAssemblerMapImpl.java | 15 +- .../DynamicInstantiationResultImpl.java | 10 +- .../graph/internal/AbstractInitializer.java | 50 +- .../sql/results/graph/tuple/TupleResult.java | 10 +- .../graph/tuple/TupleResultAssembler.java | 4 +- .../results/internal/InitializersList.java | 77 +- .../internal/LoadingCollectionEntryImpl.java | 6 +- .../NavigablePathMapToInitializer.java | 10 +- .../results/internal/NullValueAssembler.java | 3 +- .../sql/results/internal/ResultsHelper.java | 139 +-- .../RowProcessingStateStandardImpl.java | 44 +- .../results/internal/StandardRowReader.java | 138 +-- .../CircularBiDirectionalFetchImpl.java | 37 +- .../internal/domain/CircularFetchImpl.java | 102 +- .../jdbc/internal/JdbcValuesCacheHit.java | 14 +- .../JdbcValuesMappingResolutionImpl.java | 74 ++ .../internal/JdbcValuesResultSetImpl.java | 7 +- ...luesSourceProcessingStateStandardImpl.java | 2 +- .../internal/StandardJdbcValuesMapping.java | 144 ++- .../sql/results/jdbc/spi/JdbcValues.java | 12 +- .../results/jdbc/spi/JdbcValuesMapping.java | 6 +- .../jdbc/spi/JdbcValuesMappingResolution.java | 31 + .../results/jdbc/spi/RowProcessingState.java | 21 +- .../sql/results/spi/ListResultsConsumer.java | 10 +- .../hibernate/sql/results/spi/RowReader.java | 26 +- .../sql/results/spi/SingleResultConsumer.java | 4 +- .../tuple/entity/EntityMetamodel.java | 4 + .../orm/test/sql/ast/SmokeTests.java | 2 +- hibernate-envers/hibernate-envers.gradle | 7 + 138 files changed, 2802 insertions(+), 3897 deletions(-) delete mode 100644 hibernate-core/src/main/java/org/hibernate/sql/results/graph/FetchParentAccess.java create mode 100644 hibernate-core/src/main/java/org/hibernate/sql/results/graph/InitializerData.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/AggregateEmbeddableInitializer.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/LoadingEntityEntry.java create mode 100644 hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesMappingResolutionImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/spi/JdbcValuesMappingResolution.java diff --git a/hibernate-core/hibernate-core.gradle b/hibernate-core/hibernate-core.gradle index 67fe435bd8..3aeb2fb05b 100644 --- a/hibernate-core/hibernate-core.gradle +++ b/hibernate-core/hibernate-core.gradle @@ -244,6 +244,10 @@ tasks.withType( Test.class ).each { test -> test.beforeTest { descriptor -> //println "Starting test: " + descriptor } + if ( project.db == "h2" || project.db == "hsqldb" || project.db == "derby" ) { + // Parallel test runs when running with in-memory databases + test.maxParallelForks = Runtime.runtime.availableProcessors().intdiv( 2 ) ?: 1 + } } // Tests with records diff --git a/hibernate-core/src/main/java/org/hibernate/action/internal/AbstractEntityInsertAction.java b/hibernate-core/src/main/java/org/hibernate/action/internal/AbstractEntityInsertAction.java index 375f05a646..437ad96b34 100644 --- a/hibernate-core/src/main/java/org/hibernate/action/internal/AbstractEntityInsertAction.java +++ b/hibernate-core/src/main/java/org/hibernate/action/internal/AbstractEntityInsertAction.java @@ -14,6 +14,7 @@ import org.hibernate.engine.internal.Nullability; import org.hibernate.engine.spi.CachedNaturalIdValueSource; import org.hibernate.engine.spi.CollectionKey; import org.hibernate.engine.spi.EntityEntry; +import org.hibernate.engine.spi.EntityHolder; import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.Status; @@ -134,8 +135,11 @@ public abstract class AbstractEntityInsertAction extends EntityAction { nullifyTransientReferencesIfNotAlready(); final Object version = getVersion( getState(), getPersister() ); final PersistenceContext persistenceContextInternal = getSession().getPersistenceContextInternal(); - persistenceContextInternal.addEntity( getEntityKey(), getInstance() ); - persistenceContextInternal.addEntry( + final EntityHolder entityHolder = persistenceContextInternal.addEntityHolder( + getEntityKey(), + getInstance() + ); + final EntityEntry entityEntry = persistenceContextInternal.addEntry( getInstance(), ( getPersister().isMutable() ? Status.MANAGED : Status.READ_ONLY ), getState(), @@ -147,6 +151,7 @@ public abstract class AbstractEntityInsertAction extends EntityAction { getPersister(), isVersionIncrementDisabled ); + entityHolder.setEntityEntry( entityEntry ); if ( isEarlyInsert() ) { addCollectionsByKeyToPersistenceContext( persistenceContextInternal, getState() ); } diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/internal/BytecodeEnhancementMetadataPojoImpl.java b/hibernate-core/src/main/java/org/hibernate/bytecode/internal/BytecodeEnhancementMetadataPojoImpl.java index 1bbcec19fb..7cf9be90a1 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/internal/BytecodeEnhancementMetadataPojoImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/internal/BytecodeEnhancementMetadataPojoImpl.java @@ -16,6 +16,8 @@ import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterc import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributesMetadata; import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata; import org.hibernate.bytecode.spi.NotInstrumentedException; +import org.hibernate.engine.spi.EntityEntry; +import org.hibernate.engine.spi.EntityHolder; import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.ManagedEntity; import org.hibernate.engine.spi.PersistenceContext; @@ -162,7 +164,8 @@ public final class BytecodeEnhancementMetadataPojoImpl implements BytecodeEnhanc // if requested, add the "holder entry" to the PC if ( addEmptyEntry ) { - persistenceContext.addEntry( + EntityHolder entityHolder = persistenceContext.getEntityHolder( entityKey ); + EntityEntry entityEntry = persistenceContext.addEntry( entity, Status.MANAGED, // loaded state @@ -178,6 +181,7 @@ public final class BytecodeEnhancementMetadataPojoImpl implements BytecodeEnhanc persister, true ); + entityHolder.setEntityEntry( entityEntry ); } // inject the interceptor diff --git a/hibernate-core/src/main/java/org/hibernate/collection/spi/CollectionInitializerProducer.java b/hibernate-core/src/main/java/org/hibernate/collection/spi/CollectionInitializerProducer.java index 0c7f1b9b9c..533788caa2 100644 --- a/hibernate-core/src/main/java/org/hibernate/collection/spi/CollectionInitializerProducer.java +++ b/hibernate-core/src/main/java/org/hibernate/collection/spi/CollectionInitializerProducer.java @@ -12,8 +12,6 @@ import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; -import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.collection.CollectionInitializer; @@ -27,75 +25,30 @@ import org.hibernate.sql.results.graph.collection.CollectionInitializer; @Incubating @FunctionalInterface public interface CollectionInitializerProducer { + /** * Create an initializer for the given attribute relative to the given * navigable path. * * @param navigablePath the navigable path * @param attribute the attribute - * @param parentAccess may be null to indicate that the initializer is + * @param parent may be null to indicate that the initializer is * for a {@link org.hibernate.sql.results.graph.DomainResult} * rather than a {@link org.hibernate.sql.results.graph.Fetch} - * @param collectionKeyAssembler allows creation of a + * @param collectionKeyResult allows creation of a * {@link org.hibernate.sql.results.graph.DomainResult} for * either side of the collection foreign key - * @param collectionValueKeyAssembler allows creation of a + * @param collectionValueKeyResult allows creation of a * {@link org.hibernate.sql.results.graph.DomainResult} for * either side of the collection foreign key - * @deprecated Use {@link #produceInitializer(NavigablePath, PluralAttributeMapping, InitializerParent, LockMode, DomainResult, DomainResult, boolean, AssemblerCreationState)} instead */ - @Deprecated(forRemoval = true) - CollectionInitializer produceInitializer( + CollectionInitializer produceInitializer( NavigablePath navigablePath, PluralAttributeMapping attribute, - FetchParentAccess parentAccess, - LockMode lockMode, - DomainResultAssembler collectionKeyAssembler, - DomainResultAssembler collectionValueKeyAssembler, - AssemblerCreationState creationState); - - default CollectionInitializer produceInitializer( - NavigablePath navigablePath, - PluralAttributeMapping attribute, - InitializerParent parent, + InitializerParent parent, LockMode lockMode, DomainResult collectionKeyResult, DomainResult collectionValueKeyResult, boolean isResultInitializer, - AssemblerCreationState creationState) { - final DomainResultAssembler collectionKeyAssembler; - final DomainResultAssembler collectionValueKeyAssembler; - if ( collectionKeyResult == null ) { - collectionKeyAssembler = null; - collectionValueKeyAssembler = collectionValueKeyResult.createResultAssembler( - (InitializerParent) null, - creationState - ); - } - else if ( collectionKeyResult == collectionValueKeyResult ) { - collectionKeyAssembler = collectionValueKeyAssembler = collectionKeyResult.createResultAssembler( - (InitializerParent) null, - creationState - ); - } - else { - collectionKeyAssembler = collectionKeyResult.createResultAssembler( - (InitializerParent) null, - creationState - ); - collectionValueKeyAssembler = collectionValueKeyResult.createResultAssembler( - (InitializerParent) null, - creationState - ); - } - return produceInitializer( - navigablePath, - attribute, - (FetchParentAccess) parent, - lockMode, - collectionKeyAssembler, - collectionValueKeyAssembler, - creationState - ); - } + AssemblerCreationState creationState); } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java b/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java index 66dcb7ed86..3d12016bd1 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/internal/StatefulPersistenceContext.java @@ -72,6 +72,8 @@ import org.hibernate.type.CollectionType; import org.jboss.logging.Logger; +import org.checkerframework.checker.nullness.qual.Nullable; + import static org.hibernate.engine.internal.ManagedTypeHelper.asHibernateProxy; import static org.hibernate.engine.internal.ManagedTypeHelper.asManagedEntity; import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable; @@ -380,13 +382,10 @@ public class StatefulPersistenceContext implements PersistenceContext { EntityKey key, Object entity, JdbcValuesSourceProcessingState processingState, - EntityInitializer initializer) { - EntityHolderImpl holder = EntityHolderImpl.forEntity( key, key.getPersister(), entity ); - final EntityHolderImpl oldHolder = getOrInitializeEntitiesByKey().putIfAbsent( - key, - holder - ); - + EntityInitializer initializer) { + final Map entityHolderMap = getOrInitializeEntitiesByKey(); + final EntityHolderImpl oldHolder = entityHolderMap.get( key ); + final EntityHolderImpl holder; if ( oldHolder != null ) { if ( entity != null ) { assert oldHolder.entity == null || oldHolder.entity == entity; @@ -405,6 +404,9 @@ public class StatefulPersistenceContext implements PersistenceContext { } holder = oldHolder; } + else { + entityHolderMap.put( key, holder = EntityHolderImpl.forEntity( key, key.getPersister(), entity ) ); + } assert holder.entityInitializer == null || holder.entityInitializer == initializer; holder.entityInitializer = initializer; processingState.registerLoadingEntityHolder( holder ); @@ -480,21 +482,28 @@ public class StatefulPersistenceContext implements PersistenceContext { @Override public void addEntity(EntityKey key, Object entity) { - EntityHolderImpl holder = EntityHolderImpl.forEntity( key, key.getPersister(), entity ); - final EntityHolderImpl oldHolder = getOrInitializeEntitiesByKey().putIfAbsent( - key, - holder - ); + addEntityHolder( key, entity ); + } + + @Override + public EntityHolder addEntityHolder(EntityKey key, Object entity) { + final Map entityHolderMap = getOrInitializeEntitiesByKey(); + final EntityHolderImpl oldHolder = entityHolderMap.get( key ); + final EntityHolderImpl holder; if ( oldHolder != null ) { // assert oldHolder.entity == null || oldHolder.entity == entity; oldHolder.entity = entity; holder = oldHolder; } + else { + entityHolderMap.put( key, holder = EntityHolderImpl.forEntity( key, key.getPersister(), entity ) ); + } holder.state = EntityHolderState.INITIALIZED; final BatchFetchQueue fetchQueue = this.batchFetchQueue; if ( fetchQueue != null ) { fetchQueue.removeBatchLoadableEntityKey( key ); } + return holder; } @Override @@ -603,8 +612,8 @@ public class StatefulPersistenceContext implements PersistenceContext { final boolean existsInDatabase, final EntityPersister persister, final boolean disableVersionIncrement) { - addEntity( entityKey, entity ); - return addEntry( + EntityHolder entityHolder = addEntityHolder( entityKey, entity ); + EntityEntry entityEntry = addEntry( entity, status, loadedState, @@ -616,6 +625,8 @@ public class StatefulPersistenceContext implements PersistenceContext { persister, disableVersionIncrement ); + entityHolder.setEntityEntry( entityEntry ); + return entityEntry; } @Override @@ -685,7 +696,7 @@ public class StatefulPersistenceContext implements PersistenceContext { return e; } - public void addReferenceEntry( + public EntityEntry addReferenceEntry( final Object entity, final Status status) { final EntityEntry entityEntry = asManagedEntity( entity ).$$_hibernate_getEntityEntry(); @@ -693,6 +704,7 @@ public class StatefulPersistenceContext implements PersistenceContext { entityEntryContext.addEntityEntry( entity, entityEntry ); setHasNonReadOnlyEnties( status ); + return entityEntry; } @Override @@ -762,12 +774,15 @@ public class StatefulPersistenceContext implements PersistenceContext { .getEntityDescriptor( li.getEntityName() ); final EntityKey key = session.generateEntityKey( li.getInternalIdentifier(), persister ); // any earlier proxy takes precedence - final EntityHolderImpl holder = getOrInitializeEntitiesByKey().putIfAbsent( - key, - EntityHolderImpl.forProxy( key, persister, proxy ) - ); - if ( holder != null && holder.proxy == null ) { - holder.proxy = proxy; + final Map entityHolderMap = getOrInitializeEntitiesByKey(); + final EntityHolderImpl oldHolder = entityHolderMap.get( key ); + if ( oldHolder != null ) { + if ( oldHolder.proxy == null ) { + oldHolder.proxy = proxy; + } + } + else { + entityHolderMap.put( key, EntityHolderImpl.forProxy( key, persister, proxy ) ); } proxy.getHibernateLazyInitializer().setSession( session ); } @@ -912,15 +927,16 @@ public class StatefulPersistenceContext implements PersistenceContext { @Override public void addEnhancedProxy(EntityKey key, PersistentAttributeInterceptable entity) { - EntityHolderImpl holder = EntityHolderImpl.forEntity( key, key.getPersister(), entity ); - final EntityHolderImpl oldHolder = getOrInitializeEntitiesByKey().putIfAbsent( - key, - holder - ); + final Map entityHolderMap = getOrInitializeEntitiesByKey(); + final EntityHolderImpl oldHolder = entityHolderMap.get( key ); + final EntityHolderImpl holder; if ( oldHolder != null ) { oldHolder.entity = entity; holder = oldHolder; } + else { + entityHolderMap.put( key, holder = EntityHolderImpl.forEntity( key, key.getPersister(), entity ) ); + } holder.state = EntityHolderState.ENHANCED_PROXY; } @@ -1209,13 +1225,14 @@ public class StatefulPersistenceContext implements PersistenceContext { @Override public void addProxy(EntityKey key, Object proxy) { - final EntityHolderImpl holder = getOrInitializeEntitiesByKey().putIfAbsent( - key, - EntityHolderImpl.forProxy( key, key.getPersister(), proxy ) - ); + final Map entityHolderMap = getOrInitializeEntitiesByKey(); + final EntityHolderImpl holder = entityHolderMap.get( key ); if ( holder != null ) { holder.proxy = proxy; } + else { + entityHolderMap.put( key, EntityHolderImpl.forProxy( key, key.getPersister(), proxy ) ); + } } @Override @@ -1745,8 +1762,8 @@ public class StatefulPersistenceContext implements PersistenceContext { this.parentsByChild = null; final EntityKey newKey = session.generateEntityKey( generatedId, oldEntry.getPersister() ); - addEntity( newKey, entity ); - addEntry( + EntityHolder entityHolder = addEntityHolder( newKey, entity ); + EntityEntry entityEntry = addEntry( entity, oldEntry.getStatus(), oldEntry.getLoadedState(), @@ -1758,12 +1775,13 @@ public class StatefulPersistenceContext implements PersistenceContext { oldEntry.getPersister(), oldEntry.isBeingReplicated() ); + entityHolder.setEntityEntry( entityEntry ); } @Override public void replaceEntityEntryRowId(Object entity, Object rowId) { final EntityEntry oldEntry = entityEntryContext.removeEntityEntry( entity ); - addEntry( + EntityEntry entityEntry = addEntry( entity, oldEntry.getStatus(), oldEntry.getLoadedState(), @@ -1775,6 +1793,7 @@ public class StatefulPersistenceContext implements PersistenceContext { oldEntry.getPersister(), oldEntry.isBeingReplicated() ); + getEntityHolder( oldEntry.getEntityKey() ).setEntityEntry( entityEntry ); } /** @@ -1789,15 +1808,6 @@ public class StatefulPersistenceContext implements PersistenceContext { oos.writeBoolean( defaultReadOnly ); oos.writeBoolean( hasNonReadOnlyEntities ); - - writeMapToStream( entitiesByKey, oos, "entitiesByKey", (entry, stream) -> { - entry.getKey().serialize( stream ); - final EntityHolderImpl holder = entry.getValue(); - stream.writeObject( holder.descriptor.getEntityName() ); - stream.writeObject( holder.entity ); - stream.writeObject( holder.proxy ); - stream.writeObject( holder.state ); - } ); writeMapToStream( entitiesByUniqueKey, oos, "entitiesByUniqueKey", (entry, stream) -> { entry.getKey().serialize( stream ); stream.writeObject( entry.getValue() ); @@ -1808,6 +1818,15 @@ public class StatefulPersistenceContext implements PersistenceContext { } ); entityEntryContext.serialize( oos ); + + writeMapToStream( entitiesByKey, oos, "entitiesByKey", (entry, stream) -> { + entry.getKey().serialize( stream ); + final EntityHolderImpl holder = entry.getValue(); + stream.writeObject( holder.descriptor.getEntityName() ); + stream.writeObject( holder.entity ); + stream.writeObject( holder.proxy ); + stream.writeObject( holder.state ); + } ); writeMapToStream( collectionsByKey, oos, @@ -1906,6 +1925,28 @@ public class StatefulPersistenceContext implements PersistenceContext { int count = ois.readInt(); final boolean traceEnabled = LOG.isTraceEnabled(); + if ( traceEnabled ) { + LOG.trace( "Starting deserialization of [" + count + "] entitiesByUniqueKey entries" ); + } + if ( count != 0 ) { + rtn.entitiesByUniqueKey = CollectionHelper.mapOfSize(Math.max(count, INIT_COLL_SIZE)); + for ( int i = 0; i < count; i++ ) { + rtn.entitiesByUniqueKey.put( EntityUniqueKey.deserialize( ois, session ), ois.readObject() ); + } + } + + count = ois.readInt(); + if ( traceEnabled ) { + LOG.trace( "Starting deserialization of [" + count + "] entitySnapshotsByKey entries" ); + } + rtn.entitySnapshotsByKey = CollectionHelper.mapOfSize(Math.max(count, INIT_COLL_SIZE)); + for ( int i = 0; i < count; i++ ) { + rtn.entitySnapshotsByKey.put( EntityKey.deserialize( ois, sfi ), ois.readObject() ); + } + + rtn.entityEntryContext = EntityEntryContext.deserialize( ois, rtn ); + + count = ois.readInt(); if ( traceEnabled ) { LOG.trace( "Starting deserialization of [" + count + "] entitiesByKey entries" ); } @@ -1931,31 +1972,10 @@ public class StatefulPersistenceContext implements PersistenceContext { } } } + holder.setEntityEntry( rtn.entityEntryContext.getEntityEntry( entity ) ); rtn.entitiesByKey.put( ek, holder ); } - count = ois.readInt(); - if ( traceEnabled ) { - LOG.trace( "Starting deserialization of [" + count + "] entitiesByUniqueKey entries" ); - } - if ( count != 0 ) { - rtn.entitiesByUniqueKey = CollectionHelper.mapOfSize(Math.max(count, INIT_COLL_SIZE)); - for ( int i = 0; i < count; i++ ) { - rtn.entitiesByUniqueKey.put( EntityUniqueKey.deserialize( ois, session ), ois.readObject() ); - } - } - - count = ois.readInt(); - if ( traceEnabled ) { - LOG.trace( "Starting deserialization of [" + count + "] entitySnapshotsByKey entries" ); - } - rtn.entitySnapshotsByKey = CollectionHelper.mapOfSize(Math.max(count, INIT_COLL_SIZE)); - for ( int i = 0; i < count; i++ ) { - rtn.entitySnapshotsByKey.put( EntityKey.deserialize( ois, sfi ), ois.readObject() ); - } - - rtn.entityEntryContext = EntityEntryContext.deserialize( ois, rtn ); - count = ois.readInt(); if ( traceEnabled ) { LOG.trace( "Starting deserialization of [" + count + "] collectionsByKey entries" ); @@ -2158,7 +2178,8 @@ public class StatefulPersistenceContext implements PersistenceContext { private final EntityPersister descriptor; Object entity; Object proxy; - EntityInitializer entityInitializer; + @Nullable EntityEntry entityEntry; + EntityInitializer entityInitializer; EntityHolderState state; private EntityHolderImpl(EntityKey entityKey, EntityPersister descriptor, Object entity, Object proxy) { @@ -2170,6 +2191,16 @@ public class StatefulPersistenceContext implements PersistenceContext { this.state = EntityHolderState.UNINITIALIZED; } + @Override + public @Nullable EntityEntry getEntityEntry() { + return entityEntry; + } + + @Override + public void setEntityEntry(@Nullable EntityEntry entityEntry) { + this.entityEntry = entityEntry; + } + @Override public EntityKey getEntityKey() { return entityKey; @@ -2191,7 +2222,7 @@ public class StatefulPersistenceContext implements PersistenceContext { } @Override - public EntityInitializer getEntityInitializer() { + public EntityInitializer getEntityInitializer() { return entityInitializer; } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/EntityHolder.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/EntityHolder.java index 5edd6f35f4..8502197cfb 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/EntityHolder.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/EntityHolder.java @@ -7,6 +7,7 @@ package org.hibernate.engine.spi; import org.hibernate.Incubating; +import org.hibernate.Internal; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.sql.results.graph.entity.EntityInitializer; import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingState; @@ -35,7 +36,7 @@ public interface EntityHolder { * The entity initializer that claims to initialize the entity for this holder. * Will be {@code null} if entity is initialized already or the entity holder is not claimed yet. */ - @Nullable EntityInitializer getEntityInitializer(); + @Nullable EntityInitializer getEntityInitializer(); /** * The proxy if there is one and otherwise the entity. @@ -45,6 +46,11 @@ public interface EntityHolder { return proxy == null ? getEntity() : proxy; } + @Nullable EntityEntry getEntityEntry(); + + @Internal + void setEntityEntry(@Nullable EntityEntry entry); + /** * Marks the entity holder as reloaded to potentially trigger follow-on locking. * diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/EntityKey.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/EntityKey.java index 0e235afa73..58982fb95e 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/EntityKey.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/EntityKey.java @@ -58,7 +58,7 @@ public final class EntityKey implements Serializable { private int generateHashCode() { int result = 17; final String rootEntityName = persister.getRootEntityName(); - result = 37 * result + ( rootEntityName != null ? rootEntityName.hashCode() : 0 ); + result = 37 * result + rootEntityName.hashCode(); result = 37 * result + persister.getIdentifierType().getHashCode( identifier, persister.getFactory() ); return result; } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/PersistenceContext.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/PersistenceContext.java index 11b28933d4..09a54ca824 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/PersistenceContext.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/PersistenceContext.java @@ -519,7 +519,10 @@ public interface PersistenceContext { EntityKey key, @Nullable Object entity, JdbcValuesSourceProcessingState processingState, - EntityInitializer initializer); + EntityInitializer initializer); + + @Incubating + EntityHolder addEntityHolder(EntityKey key, Object entity); EntityHolder getEntityHolder(EntityKey key); diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/SubselectFetch.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/SubselectFetch.java index c61302a10a..bbebfc5383 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/SubselectFetch.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/SubselectFetch.java @@ -151,7 +151,7 @@ public class SubselectFetch { public void addKey(EntityHolder holder) { if ( batchFetchQueue.getSession().getLoadQueryInfluencers() .hasSubselectLoadableCollections( holder.getDescriptor() ) ) { - final EntityInitializer entityInitializer = NullnessUtil.castNonNull( holder.getEntityInitializer() ); + final EntityInitializer entityInitializer = NullnessUtil.castNonNull( holder.getEntityInitializer() ); final SubselectFetch subselectFetch = subselectFetches.computeIfAbsent( entityInitializer.getNavigablePath(), navigablePath -> new SubselectFetch( diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractSaveEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractSaveEventListener.java index 9dae765337..fd218493eb 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractSaveEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractSaveEventListener.java @@ -298,6 +298,9 @@ public abstract class AbstractSaveEventListener persister, false ); + if ( original.getLoadedState() != null ) { + persistenceContext.getEntityHolder( key ).setEntityEntry( original ); + } cascadeBeforeSave( source, persister, entity, context ); diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultEvictEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultEvictEventListener.java index 3cb7f9e99c..adddcc2a73 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultEvictEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultEvictEventListener.java @@ -127,7 +127,7 @@ public class DefaultEvictEventListener implements EvictEventListener { // This is now handled by removeEntity() //session.getPersistenceContext().removeDatabaseSnapshot(key); - persistenceContext.removeEntity( key ); + persistenceContext.removeEntityHolder( key ); persistenceContext.removeEntry( object ); Cascade.cascade( CascadingActions.EVICT, CascadePoint.AFTER_EVICT, session, persister, object ); diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultRefreshEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultRefreshEventListener.java index ced2a98b38..e52958462c 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultRefreshEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultRefreshEventListener.java @@ -169,11 +169,11 @@ public class DefaultRefreshEventListener implements RefreshEventListener { ); if ( entry != null ) { - final EntityKey key = source.generateEntityKey( id, persister ); - persistenceContext.removeEntity( key ); + persistenceContext.removeEntityHolder( entry.getEntityKey() ); if ( persister.hasCollections() ) { new EvictVisitor( source, object ).process( object, persister ); } + persistenceContext.removeEntry( object ); } evictEntity( object, persister, id, source ); diff --git a/hibernate-core/src/main/java/org/hibernate/generator/values/internal/GeneratedValuesHelper.java b/hibernate-core/src/main/java/org/hibernate/generator/values/internal/GeneratedValuesHelper.java index b2e690957f..56dc60c6a2 100644 --- a/hibernate-core/src/main/java/org/hibernate/generator/values/internal/GeneratedValuesHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/generator/values/internal/GeneratedValuesHelper.java @@ -15,7 +15,6 @@ import java.util.List; import org.hibernate.HibernateException; import org.hibernate.Internal; -import org.hibernate.LockOptions; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.generator.EventType; @@ -157,6 +156,7 @@ public class GeneratedValuesHelper { null, null, QueryOptions.NONE, + true, mappingProducer.resolve( directResultSetAccess, session.getLoadQueryInfluencers(), @@ -194,8 +194,7 @@ public class GeneratedValuesHelper { ); final RowReader rowReader = ResultsHelper.createRowReader( - executionContext, - LockOptions.NONE, + session.getFactory(), RowTransformerArrayImpl.instance(), Object[].class, jdbcValues diff --git a/hibernate-core/src/main/java/org/hibernate/internal/AbstractScrollableResults.java b/hibernate-core/src/main/java/org/hibernate/internal/AbstractScrollableResults.java index 099fc9f524..79a33cefe1 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/AbstractScrollableResults.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/AbstractScrollableResults.java @@ -97,7 +97,7 @@ public abstract class AbstractScrollableResults implements ScrollableResultsI return; } - rowReader.finishUp( jdbcValuesSourceProcessingState ); + rowReader.finishUp( rowProcessingState ); jdbcValues.finishUp( persistenceContext ); getPersistenceContext().getJdbcCoordinator().afterStatementExecution(); diff --git a/hibernate-core/src/main/java/org/hibernate/internal/FetchingScrollableResultsImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/FetchingScrollableResultsImpl.java index 016bc9ff16..964774c796 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/FetchingScrollableResultsImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/FetchingScrollableResultsImpl.java @@ -10,8 +10,6 @@ import org.hibernate.HibernateException; import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.sql.results.graph.Initializer; -import org.hibernate.sql.results.graph.entity.EntityInitializer; import org.hibernate.sql.results.internal.RowProcessingStateStandardImpl; import org.hibernate.sql.results.jdbc.internal.JdbcValuesSourceProcessingStateStandardImpl; import org.hibernate.sql.results.jdbc.spi.JdbcValues; @@ -315,7 +313,7 @@ public class FetchingScrollableResultsImpl extends AbstractScrollableResults< loadContexts.register( getJdbcValuesSourceProcessingState() ); persistenceContext.beforeLoad(); try { - currentRow = rowReader.readRow( rowProcessingState, getProcessingOptions() ); + currentRow = rowReader.readRow( rowProcessingState ); rowProcessingState.finishRowProcessing( true ); @@ -327,7 +325,7 @@ public class FetchingScrollableResultsImpl extends AbstractScrollableResults< last = false; } else { - rowReader.readRow( rowProcessingState, getProcessingOptions() ); + rowReader.readRow( rowProcessingState ); rowProcessingState.finishRowProcessing( false ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/ScrollableResultsImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/ScrollableResultsImpl.java index f225abd21d..c3a642d0b2 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/ScrollableResultsImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/ScrollableResultsImpl.java @@ -130,7 +130,7 @@ public class ScrollableResultsImpl extends AbstractScrollableResults { persistenceContext.beforeLoad(); try { try { - currentRow = getRowReader().readRow( getRowProcessingState(), getProcessingOptions() ); + currentRow = getRowReader().readRow( getRowProcessingState() ); getRowProcessingState().finishRowProcessing( true ); getJdbcValuesSourceProcessingState().finishUp( false ); diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CacheEntityLoaderHelper.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CacheEntityLoaderHelper.java index 9a864e33de..833cc62b96 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CacheEntityLoaderHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CacheEntityLoaderHelper.java @@ -356,11 +356,15 @@ public class CacheEntityLoaderHelper { final StatefulPersistenceContext statefulPersistenceContext = (StatefulPersistenceContext) session.getPersistenceContext(); if ( ( isManagedEntity( entity ) ) ) { - statefulPersistenceContext.addEntity( entityKey, entity ); - statefulPersistenceContext.addReferenceEntry( + final EntityHolder entityHolder = statefulPersistenceContext.addEntityHolder( + entityKey, + entity + ); + final EntityEntry entityEntry = statefulPersistenceContext.addReferenceEntry( entity, Status.READ_ONLY ); + entityHolder.setEntityEntry( entityEntry ); } else { TwoPhaseLoad.addUninitializedCachedEntity( @@ -471,7 +475,7 @@ public class CacheEntityLoaderHelper { isReadOnly = source.isDefaultReadOnly(); } - persistenceContext.addEntry( + EntityEntry entityEntry = persistenceContext.addEntry( entity, ( isReadOnly ? Status.READ_ONLY : Status.MANAGED ), values, @@ -483,6 +487,7 @@ public class CacheEntityLoaderHelper { subclassPersister, false ); + persistenceContext.getEntityHolder( entityKey ).setEntityEntry( entityEntry ); subclassPersister.afterInitialize( entity, source ); persistenceContext.initializeNonLazyCollections(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/CompoundNaturalIdMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/CompoundNaturalIdMapping.java index a43e800366..294c38b3ed 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/CompoundNaturalIdMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/CompoundNaturalIdMapping.java @@ -43,13 +43,11 @@ import org.hibernate.sql.results.graph.DomainResultAssembler; 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.FetchParentAccess; import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.graph.FetchableContainer; import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.internal.ImmutableFetchList; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.descriptor.java.JavaType; @@ -571,14 +569,7 @@ public class CompoundNaturalIdMapping extends AbstractNaturalIdMapping implement @Override public DomainResultAssembler createResultAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createResultAssembler( (InitializerParent) parentAccess, creationState ); - } - - @Override - public DomainResultAssembler createResultAssembler( - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return new AssemblerImpl( fetches, @@ -599,7 +590,7 @@ public class CompoundNaturalIdMapping extends AbstractNaturalIdMapping implement // FetchParent @Override - public Initializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { + public Initializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { throw new UnsupportedOperationException( "Compound natural id mappings should not use an initializer" ); } @@ -655,17 +646,21 @@ public class CompoundNaturalIdMapping extends AbstractNaturalIdMapping implement this.subAssemblers = new DomainResultAssembler[fetches.size()]; int i = 0; for ( Fetch fetch : fetches ) { - subAssemblers[i++] = fetch.createAssembler( (InitializerParent) null, creationState ); + subAssemblers[i++] = fetch.createAssembler( null, creationState ); } } + private AssemblerImpl(JavaType jtd, DomainResultAssembler[] subAssemblers) { + this.jtd = jtd; + this.subAssemblers = subAssemblers; + } + @Override public Object[] assemble( - RowProcessingState rowProcessingState, - JdbcValuesSourceProcessingOptions options) { + RowProcessingState rowProcessingState) { final Object[] result = new Object[ subAssemblers.length ]; for ( int i = 0; i < subAssemblers.length; i++ ) { - result[ i ] = subAssemblers[i].assemble( rowProcessingState, options ); + result[ i ] = subAssemblers[i].assemble( rowProcessingState ); } return result; } @@ -678,9 +673,9 @@ public class CompoundNaturalIdMapping extends AbstractNaturalIdMapping implement } @Override - public void forEachResultAssembler(BiConsumer consumer, X arg) { + public void forEachResultAssembler(BiConsumer, X> consumer, X arg) { for ( DomainResultAssembler subAssembler : subAssemblers ) { - final Initializer initializer = subAssembler.getInitializer(); + final Initializer initializer = subAssembler.getInitializer(); // In case of natural id mapping selection every initializer is a "result initializer", // regardless of what Initializer#isResultInitializer reports if ( initializer != null ) { @@ -693,6 +688,7 @@ public class CompoundNaturalIdMapping extends AbstractNaturalIdMapping implement public JavaType getAssembledJavaType() { return jtd; } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java index cd11a6b382..050e756b70 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java @@ -92,7 +92,6 @@ import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.Fetch; import org.hibernate.sql.results.graph.FetchOptions; import org.hibernate.sql.results.graph.FetchParent; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.graph.FetchableContainer; import org.hibernate.sql.results.graph.InitializerParent; @@ -1852,13 +1851,6 @@ public class ToOneAttributeMapping return null; } - @Override - public DomainResultAssembler createResultAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createResultAssembler( (InitializerParent) parentAccess, creationState ); - } - @Override public DomainResultAssembler createResultAssembler( InitializerParent parent, diff --git a/hibernate-core/src/main/java/org/hibernate/query/results/JdbcValuesMappingImpl.java b/hibernate-core/src/main/java/org/hibernate/query/results/JdbcValuesMappingImpl.java index 14c6e9dd65..7aa0935805 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/results/JdbcValuesMappingImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/results/JdbcValuesMappingImpl.java @@ -8,23 +8,14 @@ package org.hibernate.query.results; import java.util.List; import java.util.Map; -import java.util.function.Supplier; import org.hibernate.LockMode; -import org.hibernate.metamodel.mapping.ModelPart; -import org.hibernate.spi.NavigablePath; -import org.hibernate.sql.ast.spi.SqlAstCreationContext; import org.hibernate.sql.ast.spi.SqlSelection; -import org.hibernate.sql.exec.spi.ExecutionContext; -import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; -import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.graph.FetchParent; -import org.hibernate.sql.results.graph.Initializer; -import org.hibernate.sql.results.graph.InitializerParent; -import org.hibernate.sql.results.graph.InitializerProducer; import org.hibernate.sql.results.jdbc.internal.StandardJdbcValuesMapping; +import org.checkerframework.checker.nullness.qual.Nullable; + /** * Implementation of JdbcValuesMapping for native / procedure queries * @@ -33,13 +24,13 @@ import org.hibernate.sql.results.jdbc.internal.StandardJdbcValuesMapping; public class JdbcValuesMappingImpl extends StandardJdbcValuesMapping { private final int rowSize; - private final Map registeredLockModes; + private final @Nullable Map registeredLockModes; public JdbcValuesMappingImpl( List sqlSelections, List> domainResults, int rowSize, - Map registeredLockModes) { + @Nullable Map registeredLockModes) { super( sqlSelections, domainResults ); this.rowSize = rowSize; this.registeredLockModes = registeredLockModes; @@ -51,53 +42,7 @@ public class JdbcValuesMappingImpl extends StandardJdbcValuesMapping { } @Override - public List> resolveAssemblers(AssemblerCreationState creationState) { - final AssemblerCreationState finalCreationState; - if ( registeredLockModes == null ) { - finalCreationState = creationState; - } - else { - finalCreationState = new AssemblerCreationState() { - @Override - public LockMode determineEffectiveLockMode(String identificationVariable) { - final LockMode lockMode = registeredLockModes.get( identificationVariable ); - if ( lockMode == null ) { - return creationState.determineEffectiveLockMode( identificationVariable ); - } - return lockMode; - } - - @Override - public Initializer resolveInitializer( - NavigablePath navigablePath, - ModelPart fetchedModelPart, - Supplier producer) { - return creationState.resolveInitializer( navigablePath, fetchedModelPart, producer ); - } - - @Override - public

Initializer resolveInitializer( - P resultGraphNode, - InitializerParent parent, - InitializerProducer

producer) { - return creationState.resolveInitializer( - resultGraphNode, - parent, - (node, p, state) -> producer.createInitializer( node, p, this ) - ); - } - - @Override - public SqlAstCreationContext getSqlAstCreationContext() { - return creationState.getSqlAstCreationContext(); - } - - @Override - public ExecutionContext getExecutionContext() { - return creationState.getExecutionContext(); - } - }; - } - return super.resolveAssemblers( finalCreationState ); + public LockMode determineDefaultLockMode(String alias, LockMode defaultLockMode) { + return registeredLockModes == null ? defaultLockMode : registeredLockModes.getOrDefault( alias, defaultLockMode ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/results/ResultSetMappingSqlSelection.java b/hibernate-core/src/main/java/org/hibernate/query/results/ResultSetMappingSqlSelection.java index 556c54c352..f57a1c2eb0 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/results/ResultSetMappingSqlSelection.java +++ b/hibernate-core/src/main/java/org/hibernate/query/results/ResultSetMappingSqlSelection.java @@ -16,8 +16,6 @@ import org.hibernate.sql.ast.spi.SqlSelection; import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata; import org.hibernate.type.descriptor.ValueExtractor; -import org.hibernate.type.descriptor.java.JavaType; -import org.hibernate.type.spi.TypeConfiguration; /** * SqlSelection used in {@link ResultSetMapping} resolution. Doubles as its own @@ -47,15 +45,6 @@ public class ResultSetMappingSqlSelection implements SqlSelection, Expression, S return valueExtractor; } - @Override - public SqlSelection createSqlSelection( - int jdbcPosition, - int valuesArrayPosition, - JavaType javaType, - TypeConfiguration typeConfiguration) { - return this; - } - @Override public SqlSelection resolve(JdbcValuesMetadata jdbcResultsMetadata, SessionFactoryImplementor sessionFactory) { return this; diff --git a/hibernate-core/src/main/java/org/hibernate/query/results/complete/EntityResultImpl.java b/hibernate-core/src/main/java/org/hibernate/query/results/complete/EntityResultImpl.java index eb1551a28e..b00cf59f5f 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/results/complete/EntityResultImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/results/complete/EntityResultImpl.java @@ -19,7 +19,6 @@ import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.Fetch; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.InitializerParent; @@ -44,7 +43,6 @@ public class EntityResultImpl implements EntityResult, InitializerProducer { @@ -139,13 +138,6 @@ public class EntityResultImpl implements EntityResult, InitializerProducer createResultAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createResultAssembler( (InitializerParent) parentAccess, creationState ); - } - @Override public DomainResultAssembler createResultAssembler( InitializerParent parent, @@ -154,20 +146,20 @@ public class EntityResultImpl implements EntityResult, InitializerProducer createInitializer( EntityResultImpl resultGraphNode, - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return resultGraphNode.createInitializer( parent, creationState ); } @Override - public Initializer createInitializer( - InitializerParent parent, + public Initializer createInitializer( + InitializerParent parent, AssemblerCreationState creationState) { return new EntityInitializerImpl( this, - lockMode, + resultAlias, identifierFetch, discriminatorFetch, null, @@ -177,26 +169,5 @@ public class EntityResultImpl implements EntityResult, InitializerProducer extends AbstractSqmPathInterpret return getDiscriminatorMapping(); } - @Override - public SqlSelection createSqlSelection( - int jdbcPosition, - int valuesArrayPosition, - JavaType javaType, - TypeConfiguration typeConfiguration) { - return new ResultSetMappingSqlSelection( valuesArrayPosition, getDiscriminatorMapping() ); - } - @Override public DomainResult createDomainResult(String resultVariable, DomainResultCreationState creationState) { return getDiscriminatorMapping().createDomainResult( getNavigablePath(), getTableGroup(), resultVariable, creationState ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/SqmMapEntryResult.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/SqmMapEntryResult.java index 513a30d3a1..a4e685f6e3 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/SqmMapEntryResult.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/SqmMapEntryResult.java @@ -13,11 +13,8 @@ import java.util.function.BiConsumer; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.InitializerParent; -import org.hibernate.sql.results.graph.instantiation.internal.ArgumentReader; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.descriptor.java.JavaType; @@ -49,44 +46,18 @@ public class SqmMapEntryResult> implements Domai @Override public DomainResultAssembler createResultAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createResultAssembler( (InitializerParent) parentAccess, creationState ); - } - - @Override - public DomainResultAssembler createResultAssembler( - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { final DomainResultAssembler keyAssembler = keyResult.createResultAssembler( - (InitializerParent) null, + null, creationState ); final DomainResultAssembler valueAssembler = valueResult.createResultAssembler( - (InitializerParent) null, + null, creationState ); - return new DomainResultAssembler<>() { - @Override - public R assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) { - final K key = keyAssembler.assemble( rowProcessingState, options ); - final V value = valueAssembler.assemble( rowProcessingState, options ); - //noinspection unchecked - return (R) Map.entry( key, value ); - } - - @Override - public JavaType getAssembledJavaType() { - return javaType; - } - - @Override - public void forEachResultAssembler(BiConsumer consumer, X arg) { - keyAssembler.forEachResultAssembler( consumer, arg ); - valueAssembler.forEachResultAssembler( consumer, arg ); - } - }; + return new EntryDomainResultAssembler<>( javaType, keyAssembler, valueAssembler ); } @Override @@ -99,4 +70,37 @@ public class SqmMapEntryResult> implements Domai keyResult.collectValueIndexesToCache( valueIndexes ); valueResult.collectValueIndexesToCache( valueIndexes ); } + + private static class EntryDomainResultAssembler implements DomainResultAssembler { + private final JavaType javaType; + private final DomainResultAssembler keyAssembler; + private final DomainResultAssembler valueAssembler; + + public EntryDomainResultAssembler( + JavaType javaType, DomainResultAssembler keyAssembler, + DomainResultAssembler valueAssembler) { + this.javaType = javaType; + this.keyAssembler = keyAssembler; + this.valueAssembler = valueAssembler; + } + + @Override + public R assemble(RowProcessingState rowProcessingState) { + final K key = keyAssembler.assemble( rowProcessingState ); + final V value = valueAssembler.assemble( rowProcessingState ); + //noinspection unchecked + return (R) Map.entry( key, value ); + } + + @Override + public JavaType getAssembledJavaType() { + return javaType; + } + + @Override + public void forEachResultAssembler(BiConsumer, X> consumer, X arg) { + keyAssembler.forEachResultAssembler( consumer, arg ); + valueAssembler.forEachResultAssembler( consumer, arg ); + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/result/internal/OutputsImpl.java b/hibernate-core/src/main/java/org/hibernate/result/internal/OutputsImpl.java index c966be1698..9ba71104b6 100644 --- a/hibernate-core/src/main/java/org/hibernate/result/internal/OutputsImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/result/internal/OutputsImpl.java @@ -16,7 +16,6 @@ import java.util.List; import java.util.function.Supplier; import org.hibernate.JDBCException; -import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.jdbc.spi.SqlStatementLogger; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.event.spi.EventManager; @@ -194,6 +193,7 @@ public class OutputsImpl implements Outputs { null, null, this.context.getQueryOptions(), + true, resultSetMapping.resolve( resultSetAccess, context.getSession().getLoadQueryInfluencers(), getSessionFactory() ), null, executionContext @@ -203,8 +203,7 @@ public class OutputsImpl implements Outputs { //noinspection unchecked final RowReader rowReader = (RowReader) ResultsHelper.createRowReader( - executionContext, - null, + getSessionFactory(), RowTransformerStandardImpl.INSTANCE, null, jdbcValues @@ -241,18 +240,18 @@ public class OutputsImpl implements Outputs { processingOptions ); final ArrayList results = new ArrayList<>(); + final RowProcessingStateStandardImpl rowProcessingState = new RowProcessingStateStandardImpl( + jdbcValuesSourceProcessingState, + executionContext, + rowReader, + jdbcValues + ); try { - final RowProcessingStateStandardImpl rowProcessingState = new RowProcessingStateStandardImpl( - jdbcValuesSourceProcessingState, - executionContext, - rowReader, - jdbcValues - ); rowReader.startLoading( rowProcessingState ); while ( rowProcessingState.next() ) { - results.add( rowReader.readRow( rowProcessingState, processingOptions ) ); + results.add( rowReader.readRow( rowProcessingState ) ); rowProcessingState.finishRowProcessing( true ); } if ( resultSetMapping.getNumberOfResultBuilders() == 0 @@ -267,7 +266,7 @@ public class OutputsImpl implements Outputs { return results; } finally { - rowReader.finishUp( jdbcValuesSourceProcessingState ); + rowReader.finishUp( rowProcessingState ); jdbcValuesSourceProcessingState.finishUp( results.size() > 1 ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/SqlSelectionProducer.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/SqlSelectionProducer.java index e4aef2b578..d6768c89c3 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/SqlSelectionProducer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/SqlSelectionProducer.java @@ -14,21 +14,6 @@ import org.hibernate.type.spi.TypeConfiguration; * @author Steve Ebersole */ public interface SqlSelectionProducer { - /** - * Create a SqlSelection for the given JDBC ResultSet position - * - * @param jdbcPosition The index position used to read values from JDBC - * @param valuesArrayPosition The position in our {@linkplain RowProcessingState#getJdbcValue(SqlSelection) "current JDBC values array"} - * @param javaType The descriptor for the Java type to read the value as - * @param typeConfiguration The associated TypeConfiguration - * @deprecated Use {@link #createSqlSelection(int, int, JavaType, boolean, TypeConfiguration)} instead - */ - @Deprecated(forRemoval = true) - SqlSelection createSqlSelection( - int jdbcPosition, - int valuesArrayPosition, - JavaType javaType, - TypeConfiguration typeConfiguration); /** * Create a SqlSelection for the given JDBC ResultSet position diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/Expression.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/Expression.java index cef05335e0..d56f9677ea 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/Expression.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/expression/Expression.java @@ -29,21 +29,6 @@ public interface Expression extends SqlAstNode, SqlSelectionProducer { return null; } - @Override - default SqlSelection createSqlSelection( - int jdbcPosition, - int valuesArrayPosition, - JavaType javaType, - TypeConfiguration typeConfiguration) { - return new SqlSelectionImpl( - jdbcPosition, - valuesArrayPosition, - javaType, - this, - false - ); - } - @Override default SqlSelection createSqlSelection( int jdbcPosition, @@ -60,15 +45,6 @@ public interface Expression extends SqlAstNode, SqlSelectionProducer { ); } - @Deprecated(forRemoval = true) - default SqlSelection createDomainResultSqlSelection( - int jdbcPosition, - int valuesArrayPosition, - JavaType javaType, - TypeConfiguration typeConfiguration) { - return createDomainResultSqlSelection( jdbcPosition, valuesArrayPosition, javaType, false, typeConfiguration ); - } - default SqlSelection createDomainResultSqlSelection( int jdbcPosition, int valuesArrayPosition, diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/DelegatingTableGroup.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/DelegatingTableGroup.java index 2189dc6c32..6ca3b35dbe 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/DelegatingTableGroup.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/DelegatingTableGroup.java @@ -44,20 +44,6 @@ public abstract class DelegatingTableGroup implements TableGroup { return getTableGroup().getColumnReference(); } - @Override - public SqlSelection createSqlSelection( - int jdbcPosition, - int valuesArrayPosition, - JavaType javaType, - TypeConfiguration typeConfiguration) { - return getTableGroup().createSqlSelection( - jdbcPosition, - valuesArrayPosition, - javaType, - typeConfiguration - ); - } - @Override public SqlSelection createSqlSelection( int jdbcPosition, diff --git a/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/AbstractJdbcParameter.java b/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/AbstractJdbcParameter.java index 3507d4726a..aa8e1d6683 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/AbstractJdbcParameter.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/AbstractJdbcParameter.java @@ -21,19 +21,15 @@ import org.hibernate.metamodel.mapping.SqlExpressible; import org.hibernate.metamodel.model.domain.internal.BasicTypeImpl; import org.hibernate.query.BindableType; import org.hibernate.sql.ast.SqlAstWalker; -import org.hibernate.sql.ast.spi.SqlSelection; import org.hibernate.sql.ast.tree.expression.JdbcParameter; import org.hibernate.sql.exec.ExecutionException; import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.exec.spi.JdbcParameterBinder; import org.hibernate.sql.exec.spi.JdbcParameterBinding; import org.hibernate.sql.exec.spi.JdbcParameterBindings; -import org.hibernate.sql.results.internal.SqlSelectionImpl; import org.hibernate.type.descriptor.java.EnumJavaType; -import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators; -import org.hibernate.type.spi.TypeConfiguration; /** * @author Steve Ebersole @@ -67,19 +63,6 @@ public abstract class AbstractJdbcParameter sqlTreeWalker.visitParameter( this ); } - @Override - public SqlSelection createSqlSelection( - int jdbcPosition, - int valuesArrayPosition, - JavaType javaType, - TypeConfiguration typeConfiguration) { - // todo (6.0) : investigate "virtual" or "static" selections - // - anything that is the same for each row always - parameter, literal, etc; - // the idea would be to write the value directly into the JdbcValues array - // and not generating a SQL selection in the query sent to DB - return new SqlSelectionImpl( jdbcPosition, valuesArrayPosition, javaType, this, false ); - } - @Override public JdbcMapping getSingleJdbcMapping() { return jdbcMapping; diff --git a/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/JdbcSelectExecutorStandardImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/JdbcSelectExecutorStandardImpl.java index 4b1e7f7721..07d7910d63 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/JdbcSelectExecutorStandardImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/exec/internal/JdbcSelectExecutorStandardImpl.java @@ -14,7 +14,6 @@ import java.util.concurrent.TimeUnit; import java.util.function.Function; import org.hibernate.CacheMode; -import org.hibernate.LockOptions; import org.hibernate.cache.spi.QueryKey; import org.hibernate.cache.spi.QueryResultsCache; import org.hibernate.engine.spi.PersistenceContext; @@ -186,14 +185,7 @@ public class JdbcSelectExecutorStandardImpl implements JdbcSelectExecutor { ); final RowReader rowReader = ResultsHelper.createRowReader( - executionContext, - // If follow-on locking is used, we must omit the lock options here, - // because these lock options are only for Initializers. - // If we wouldn't omit this, the follow-on lock requests would be no-ops, - // because the EntityEntrys would already have the desired lock mode - deferredResultSetAccess.usesFollowOnLocking() - ? LockOptions.NONE - : executionContext.getQueryOptions().getLockOptions(), + session.getFactory(), rowTransformer, domainResultType, jdbcValues @@ -237,12 +229,12 @@ public class JdbcSelectExecutorStandardImpl implements JdbcSelectExecutor { return -1; } - public JdbcValues resolveJdbcValuesSource( + private JdbcValues resolveJdbcValuesSource( String queryIdentifier, JdbcOperationQuerySelect jdbcSelect, boolean canBeCached, ExecutionContext executionContext, - ResultSetAccess resultSetAccess) { + DeferredResultSetAccess resultSetAccess) { final SharedSessionContractImplementor session = executionContext.getSession(); final SessionFactoryImplementor factory = session.getFactory(); final boolean queryCacheEnabled = factory.getSessionFactoryOptions().isQueryCacheEnabled(); @@ -339,6 +331,7 @@ public class JdbcSelectExecutorStandardImpl implements JdbcSelectExecutor { queryResultsCacheKey, queryIdentifier, executionContext.getQueryOptions(), + resultSetAccess.usesFollowOnLocking(), jdbcValuesMapping, metadataForCache, executionContext diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/AssemblerCreationState.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/AssemblerCreationState.java index 09164b00e4..dd029b7e33 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/AssemblerCreationState.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/AssemblerCreationState.java @@ -8,37 +8,31 @@ package org.hibernate.sql.results.graph; import java.util.function.Supplier; -import org.hibernate.LockMode; import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.ast.spi.SqlAstCreationContext; -import org.hibernate.sql.exec.spi.ExecutionContext; /** * @author Steve Ebersole */ public interface AssemblerCreationState { - default boolean isScrollResult() { - return false; - } default boolean isDynamicInstantiation() { return false; } - LockMode determineEffectiveLockMode(String identificationVariable); + int acquireInitializerId(); - Initializer resolveInitializer( + Initializer resolveInitializer( NavigablePath navigablePath, ModelPart fetchedModelPart, - Supplier producer); + Supplier> producer); -

Initializer resolveInitializer( +

Initializer resolveInitializer( P resultGraphNode, - InitializerParent parent, + InitializerParent parent, InitializerProducer

producer); SqlAstCreationContext getSqlAstCreationContext(); - ExecutionContext getExecutionContext(); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/DomainResult.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/DomainResult.java index 4083505a1d..c8ae41f2cd 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/DomainResult.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/DomainResult.java @@ -30,19 +30,8 @@ public interface DomainResult extends DomainResultGraphNode { /** * Create an assembler (and any initializers) for this result. - * @deprecated Use {@link #createResultAssembler(InitializerParent, AssemblerCreationState)} instead. */ - @Deprecated(forRemoval = true) DomainResultAssembler createResultAssembler( - FetchParentAccess parentAccess, + InitializerParent parent, AssemblerCreationState creationState); - - /** - * Create an assembler (and any initializers) for this result. - */ - default DomainResultAssembler createResultAssembler( - InitializerParent parent, - AssemblerCreationState creationState) { - return createResultAssembler( (FetchParentAccess) parent, creationState ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/DomainResultAssembler.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/DomainResultAssembler.java index ab903a9718..d717a59ab4 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/DomainResultAssembler.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/DomainResultAssembler.java @@ -9,7 +9,6 @@ package org.hibernate.sql.results.graph; import java.util.function.BiConsumer; import org.hibernate.Incubating; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.descriptor.java.JavaType; @@ -28,14 +27,7 @@ public interface DomainResultAssembler { /** * The main "assembly" contract. Assemble the result and return it. */ - @Nullable J assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options); - - /** - * Convenience form of {@link #assemble(RowProcessingState, JdbcValuesSourceProcessingOptions)} - */ - default @Nullable J assemble(RowProcessingState rowProcessingState) { - return assemble( rowProcessingState, rowProcessingState.getJdbcValuesSourceProcessingState().getProcessingOptions() ); - } + @Nullable J assemble(RowProcessingState rowProcessingState); /** * The JavaType describing the Java type that this assembler @@ -51,7 +43,7 @@ public interface DomainResultAssembler { assemble( rowProcessingState ); } - default @Nullable Initializer getInitializer() { + default @Nullable Initializer getInitializer() { return null; } @@ -59,7 +51,8 @@ public interface DomainResultAssembler { * Invokes the consumer with every initializer part of this assembler that returns {@code true} for * {@link Initializer#isResultInitializer()}. */ - default void forEachResultAssembler(BiConsumer consumer, X arg) { + default void forEachResultAssembler(BiConsumer, X> consumer, X arg) { } + } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/Fetch.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/Fetch.java index 61fa73502d..f5d43761af 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/Fetch.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/Fetch.java @@ -69,17 +69,8 @@ public interface Fetch extends DomainResultGraphNode { /** * Create the assembler for this fetch - * @deprecated Use {@link #createAssembler(InitializerParent, AssemblerCreationState)} instead. */ - @Deprecated(forRemoval = true) - DomainResultAssembler createAssembler(FetchParentAccess parentAccess, AssemblerCreationState creationState); - - /** - * Create the assembler for this fetch - */ - default DomainResultAssembler createAssembler( - InitializerParent parent, - AssemblerCreationState creationState) { - return createAssembler( (FetchParentAccess) parent, creationState ); - } + DomainResultAssembler createAssembler( + InitializerParent parent, + AssemblerCreationState creationState); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/FetchParent.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/FetchParent.java index 4611c85f80..9e5697044e 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/FetchParent.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/FetchParent.java @@ -102,7 +102,7 @@ public interface FetchParent extends DomainResultGraphNode { } } - Initializer createInitializer(InitializerParent parent, AssemblerCreationState creationState); + Initializer createInitializer(InitializerParent parent, AssemblerCreationState creationState); default FetchParent getRoot() { if ( this instanceof Fetch ) { diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/FetchParentAccess.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/FetchParentAccess.java deleted file mode 100644 index 00f701259f..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/FetchParentAccess.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later - * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html - */ -package org.hibernate.sql.results.graph; - -import java.util.function.Consumer; - -import org.hibernate.metamodel.mapping.AttributeMapping; -import org.hibernate.metamodel.mapping.EmbeddableMappingType; -import org.hibernate.metamodel.mapping.EntityMappingType; -import org.hibernate.metamodel.mapping.ModelPart; -import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.spi.NavigablePath; -import org.hibernate.sql.results.graph.collection.internal.AbstractImmediateCollectionInitializer; -import org.hibernate.sql.results.graph.embeddable.EmbeddableInitializer; -import org.hibernate.sql.results.graph.entity.EntityInitializer; -import org.hibernate.sql.results.jdbc.spi.RowProcessingState; - -import org.checkerframework.checker.nullness.qual.Nullable; - -/** - * Provides access to information about the owner/parent of a fetch - * in relation to the current "row" being processed. - * - * @author Steve Ebersole - */ -public interface FetchParentAccess extends InitializerParent { - /** - * Find the first entity access up the fetch parent graph - * @deprecated use {@link #findOwningEntityInitializer()} instead - */ - @Deprecated(forRemoval = true) - default @Nullable EntityInitializer findFirstEntityDescriptorAccess() { - return findOwningEntityInitializer(); - } - - default @Nullable EntityInitializer findFirstEntityInitializer() { - // Keep this method around for binary backwards compatibility - return InitializerParent.super.findFirstEntityInitializer(); - } - - /** - * @deprecated Use {@link EntityInitializer#getEntityIdentifier()} on {@link #findFirstEntityInitializer()} instead. - */ - @Deprecated(forRemoval = true) - default @Nullable Object getParentKey() { - EntityInitializer entityInitializer = asEntityInitializer(); - return entityInitializer == null || ( entityInitializer = findOwningEntityInitializer() ) == null - ? null - : entityInitializer.getEntityIdentifier(); - } - - NavigablePath getNavigablePath(); - - /** - * Register a listener to be notified when the parent is "resolved" - * - * @apiNote If already resolved, the callback is triggered immediately - * @deprecated Not used anymore - */ - @Deprecated(forRemoval = true) - default void registerResolutionListener(Consumer resolvedParentConsumer) { - throw new UnsupportedOperationException( "Don't use this method. It will be removed." ); - } - - /** - * @deprecated Use {@link #getParent()} instead - */ - @Deprecated(forRemoval = true) - default @Nullable FetchParentAccess getFetchParentAccess() { - return null; - } - - @Override - default @Nullable InitializerParent getParent() { - return getFetchParentAccess(); - } - - /** - * @deprecated Not needed anymore. - */ - @Deprecated(forRemoval = true) - default boolean shouldSkipInitializer(RowProcessingState rowProcessingState) { - return false; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/Initializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/Initializer.java index fed2867494..35fae93cd6 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/Initializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/Initializer.java @@ -11,7 +11,6 @@ import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.spi.EntityIdentifierNavigablePath; import org.hibernate.spi.NavigablePath; -import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.results.graph.collection.CollectionInitializer; import org.hibernate.sql.results.graph.embeddable.EmbeddableInitializer; import org.hibernate.sql.results.graph.entity.EntityInitializer; @@ -27,77 +26,59 @@ import org.checkerframework.checker.nullness.qual.Nullable; * @author Steve Ebersole */ @Incubating -public interface Initializer { +public interface Initializer { - Initializer[] EMPTY_ARRAY = new Initializer[0]; + Initializer[] EMPTY_ARRAY = new Initializer[0]; /** * Returns the parent {@link Initializer} or {@code null} if this is a result initializer. */ - default @Nullable InitializerParent getParent() { + default @Nullable InitializerParent getParent() { return null; } - /** - * Find the first entity access up the fetch parent graph - * @deprecated use {@link #findOwningEntityInitializer()} instead - */ - @Deprecated(forRemoval = true) - default @Nullable EntityInitializer findFirstEntityDescriptorAccess() { - return findOwningEntityInitializer(); - } - /** * Find the entity initializer that owns this initializer * by traversing up {@link #getParent()}. */ - default @Nullable EntityInitializer findOwningEntityInitializer() { + default @Nullable EntityInitializer findOwningEntityInitializer() { return Initializer.findOwningEntityInitializer( getParent() ); } /** * Find the entity initializer that owns this initializer * by traversing up {@link #getParent()}. */ - static @Nullable EntityInitializer findOwningEntityInitializer(@Nullable Initializer parent) { + static @Nullable EntityInitializer findOwningEntityInitializer(@Nullable Initializer parent) { if ( parent == null || parent.isCollectionInitializer() ) { return null; } - final EntityInitializer entityInitializer = parent.asEntityInitializer(); + final EntityInitializer entityInitializer = parent.asEntityInitializer(); if ( entityInitializer != null ) { return entityInitializer; } return findOwningEntityInitializer( parent.getParent() ); } - /** - * Find the first {@link EntityInitializer}, - * returning {@code this} if {@link #isEntityInitializer()} returns {@code true}. - * @deprecated Use {@link #findOwningEntityInitializer()} instead, optionally in combination with - * {@link #asEntityInitializer()} if the type of the {@code this} {@link Initializer} is unknown. - */ - @Deprecated(forRemoval = true) - default @Nullable EntityInitializer findFirstEntityInitializer() { - final EntityInitializer entityInitializer = this.asEntityInitializer(); - if ( entityInitializer != null ) { - return entityInitializer; - } - return findOwningEntityInitializer(); - } - NavigablePath getNavigablePath(); ModelPart getInitializedPart(); - Object getInitializedInstance(); + default Object getResolvedInstance(Data data) { + return data.getState() == State.RESOLVED || data.getState() == State.INITIALIZED ? data.getInstance() : null; + } + default Object getResolvedInstance(RowProcessingState rowProcessingState) { + return getResolvedInstance( getData( rowProcessingState ) ); + } /** - * The current state of this initializer. + * The current data of this initializer. */ - State getState(); + Data getData(RowProcessingState rowProcessingState); /** * Step 0 - Callback for initializers before the first row is read. - * It is the responsibility of this initializer to recurse to the sub-initializers. + * It is the responsibility of this initializer to recurse to the sub-initializers + * and register {@link InitializerData} for the initializer id via {@link RowProcessingState#setInitializerData(int, InitializerData)}. * * This is useful for e.g. preparing initializers in case of a cache hit. */ @@ -111,7 +92,11 @@ public interface Initializer { * After this point, the initializer knows whether further processing is necessary * for the current row i.e. if the object is missing. */ - void resolveKey(); + void resolveKey(Data data); + + default void resolveKey(RowProcessingState rowProcessingState) { + resolveKey( getData( rowProcessingState ) ); + } /** * Step 2.1 - Using the key resolved in {@link #resolveKey}, resolve the @@ -119,9 +104,13 @@ public interface Initializer { * * After this point, the initializer knows the entity/collection/component * instance for the current row based on the resolved key. - * If the resolving was successful, {@link #getInitializedInstance()} will return that instance. + * If the resolving was successful, {@link #getResolvedInstance(RowProcessingState)} will return that instance. */ - void resolveInstance(); + void resolveInstance(Data data); + + default void resolveInstance(RowProcessingState rowProcessingState) { + resolveInstance( getData( rowProcessingState ) ); + } /** * Step 2.2 - Use the given instance as resolved instance for this initializer. @@ -129,8 +118,12 @@ public interface Initializer { * * This alternative initialization protocol is used when a parent instance was already part of the persistence context. */ - default void resolveInstance(@Nullable Object instance) { - resolveKey(); + default void resolveInstance(@Nullable Object instance, Data data) { + resolveKey( data ); + } + + default void resolveInstance(@Nullable Object instance, RowProcessingState rowProcessingState) { + resolveInstance( instance, getData( rowProcessingState ) ); } /** @@ -140,7 +133,11 @@ public interface Initializer { * All resolved state for the current row is injected into the resolved * instance */ - void initializeInstance(); + void initializeInstance(Data data); + + default void initializeInstance(RowProcessingState rowProcessingState) { + initializeInstance( getData( rowProcessingState ) ); + } /** * Step 3.1 - Initialize the state of the instance as extracted from the given parentInstance. @@ -151,7 +148,11 @@ public interface Initializer { * in which case there is no data available in the {@link org.hibernate.sql.results.jdbc.internal.JdbcValuesCacheHit} * to initialize potentially lazy associations. */ - default void initializeInstanceFromParent(Object parentInstance) { + default void initializeInstanceFromParent(Object parentInstance, Data data) { + } + + default void initializeInstanceFromParent(Object parentInstance, RowProcessingState rowProcessingState) { + initializeInstanceFromParent( parentInstance, getData( rowProcessingState ) ); } /** @@ -159,29 +160,32 @@ public interface Initializer { * Provides ability to complete processing from the current row and * prepare for the next row. */ - void finishUpRow(); + void finishUpRow(Data data); + + default void finishUpRow(RowProcessingState rowProcessingState) { + finishUpRow( getData( rowProcessingState ) ); + } /** * Lifecycle method called at the very end of the result values processing */ - default void endLoading(ExecutionContext executionContext) { + default void endLoading(Data data) { // by default - nothing to do } + default void endLoading(RowProcessingState rowProcessingState) { + final Data data = getData( rowProcessingState ); + if ( data != null ) { + endLoading( data ); + } + } + /** * Indicates whether this initializer is part of a key i.e. entity identifier, foreign key or collection key. */ boolean isPartOfKey(); - /** - * @deprecated Use {@link #isPartOfKey(NavigablePath, InitializerParent)} instead. - */ - @Deprecated(forRemoval = true) - static boolean isPartOfKey(NavigablePath navigablePath, FetchParentAccess parentAccess) { - return isPartOfKey( navigablePath, (InitializerParent) parentAccess ); - } - - static boolean isPartOfKey(NavigablePath navigablePath, InitializerParent parent) { + static boolean isPartOfKey(NavigablePath navigablePath, InitializerParent parent) { return parent != null && parent.isEmbeddableInitializer() && parent.isPartOfKey() || navigablePath instanceof EntityIdentifierNavigablePath || ForeignKeyDescriptor.PART_NAME.equals( navigablePath.getLocalName() ) @@ -210,7 +214,7 @@ public interface Initializer { * * @return EntityInitializer if this is an instance of EntityInitializer otherwise {@code null} */ - default @Nullable EntityInitializer asEntityInitializer() { + default @Nullable EntityInitializer asEntityInitializer() { return null; } @@ -219,7 +223,7 @@ public interface Initializer { * * @return EmbeddableInitializer if this is an instance of EmbeddableInitializer otherwise {@code null} */ - default @Nullable EmbeddableInitializer asEmbeddableInitializer() { + default @Nullable EmbeddableInitializer asEmbeddableInitializer() { return null; } @@ -228,7 +232,7 @@ public interface Initializer { * * @return CollectionInitializer if this is an instance of CollectionInitializer otherwise {@code null} */ - default @Nullable CollectionInitializer asCollectionInitializer() { + default @Nullable CollectionInitializer asCollectionInitializer() { return null; } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/InitializerData.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/InitializerData.java new file mode 100644 index 0000000000..0e7d4ae80d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/InitializerData.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.sql.results.graph; + +import org.hibernate.sql.results.jdbc.spi.RowProcessingState; + +import org.checkerframework.checker.nullness.qual.Nullable; + +public abstract class InitializerData { + protected final RowProcessingState rowProcessingState; + protected Initializer.State state = Initializer.State.UNINITIALIZED; + protected @Nullable Object instance; + + public InitializerData(RowProcessingState rowProcessingState) { + this.rowProcessingState = rowProcessingState; + } + + public RowProcessingState getRowProcessingState() { + return rowProcessingState; + } + + public Initializer.State getState() { + return state; + } + + public void setState(Initializer.State state) { + this.state = state; + } + + public @Nullable Object getInstance() { + return instance; + } + + public void setInstance(@Nullable Object instance) { + this.instance = instance; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/InitializerParent.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/InitializerParent.java index f06f28122a..b10f874123 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/InitializerParent.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/InitializerParent.java @@ -12,6 +12,6 @@ package org.hibernate.sql.results.graph; * * @author Steve Ebersole */ -public interface InitializerParent extends Initializer { +public interface InitializerParent extends Initializer { } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/InitializerProducer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/InitializerProducer.java index 9ec8350d2a..b6271cbbcb 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/InitializerProducer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/InitializerProducer.java @@ -13,8 +13,8 @@ package org.hibernate.sql.results.graph; * @since 6.5 */ public interface InitializerProducer

{ - Initializer createInitializer( + Initializer createInitializer( P resultGraphNode, - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/UnfetchedBasicPartResultAssembler.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/UnfetchedBasicPartResultAssembler.java index 702ba61481..e3f26fcb8b 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/UnfetchedBasicPartResultAssembler.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/UnfetchedBasicPartResultAssembler.java @@ -6,7 +6,6 @@ */ package org.hibernate.sql.results.graph; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.descriptor.java.JavaType; @@ -19,7 +18,7 @@ public class UnfetchedBasicPartResultAssembler implements DomainResultAssemb } @Override - public J assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) { + public J assemble(RowProcessingState rowProcessingState) { return null; } @@ -27,4 +26,5 @@ public class UnfetchedBasicPartResultAssembler implements DomainResultAssemb public JavaType getAssembledJavaType() { return javaType; } + } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/UnfetchedResultAssembler.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/UnfetchedResultAssembler.java index 221a7f358f..d1dc1c4e79 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/UnfetchedResultAssembler.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/UnfetchedResultAssembler.java @@ -7,7 +7,6 @@ package org.hibernate.sql.results.graph; import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.descriptor.java.JavaType; @@ -23,7 +22,7 @@ public class UnfetchedResultAssembler implements DomainResultAssembler { } @Override - public J assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) { + public J assemble(RowProcessingState rowProcessingState) { return (J) LazyPropertyInitializer.UNFETCHED_PROPERTY; } @@ -31,5 +30,6 @@ public class UnfetchedResultAssembler implements DomainResultAssembler { public JavaType getAssembledJavaType() { return javaType; } + } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/basic/BasicFetch.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/basic/BasicFetch.java index d11cccfed8..c1c4d2c71c 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/basic/BasicFetch.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/basic/BasicFetch.java @@ -20,7 +20,6 @@ import org.hibernate.sql.results.graph.DomainResultAssembler; 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.FetchParentAccess; import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.type.descriptor.java.JavaType; @@ -127,30 +126,16 @@ public class BasicFetch implements Fetch, BasicResultGraphNode { return navigablePath; } - @Override - public DomainResultAssembler createAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createAssembler( (InitializerParent) parentAccess, creationState ); - } - @Override public DomainResultAssembler createAssembler( - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return assembler; } @Override public DomainResultAssembler createResultAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createResultAssembler( (InitializerParent) parentAccess, creationState ); - } - - @Override - public DomainResultAssembler createResultAssembler( - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return assembler; } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/basic/BasicResult.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/basic/BasicResult.java index e0c3124069..944c8610b8 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/basic/BasicResult.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/basic/BasicResult.java @@ -16,7 +16,6 @@ import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.type.descriptor.java.JavaType; /** @@ -110,14 +109,7 @@ public class BasicResult implements DomainResult, BasicResultGraphNode @Override public DomainResultAssembler createResultAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createResultAssembler( (InitializerParent) parentAccess, creationState ); - } - - @Override - public DomainResultAssembler createResultAssembler( - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return assembler; } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/basic/BasicResultAssembler.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/basic/BasicResultAssembler.java index 2274c845ec..f803613d5e 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/basic/BasicResultAssembler.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/basic/BasicResultAssembler.java @@ -12,9 +12,7 @@ import org.hibernate.HibernateException; import org.hibernate.Internal; import org.hibernate.type.descriptor.converter.spi.BasicValueConverter; import org.hibernate.sql.ast.spi.SqlSelection; -import org.hibernate.sql.results.ResultsLogger; import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.descriptor.java.JavaType; @@ -58,12 +56,9 @@ public class BasicResultAssembler implements DomainResultAssembler { @Override public J assemble( - RowProcessingState rowProcessingState, - JdbcValuesSourceProcessingOptions options) { + RowProcessingState rowProcessingState) { final Object jdbcValue = extractRawValue( rowProcessingState ); - ResultsLogger.RESULTS_LOGGER.debugf( "Extracted JDBC value [%d] - [%s]", valuesArrayPosition, jdbcValue ); - if ( valueConverter != null ) { if ( jdbcValue != null ) { // the raw value type should be the converter's relational-JTD diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/CollectionInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/CollectionInitializer.java index 98ceb82334..f3efc1bd18 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/CollectionInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/CollectionInitializer.java @@ -7,12 +7,10 @@ package org.hibernate.sql.results.graph.collection; import org.hibernate.collection.spi.PersistentCollection; -import org.hibernate.engine.spi.CollectionKey; -import org.hibernate.sql.results.graph.FetchParentAccess; -import org.hibernate.sql.results.graph.Initializer; import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.persister.collection.CollectionPersister; -import org.hibernate.sql.exec.spi.ExecutionContext; +import org.hibernate.sql.results.graph.InitializerData; +import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.checkerframework.checker.nullness.qual.Nullable; @@ -22,7 +20,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; * * @author Steve Ebersole */ -public interface CollectionInitializer extends FetchParentAccess { +public interface CollectionInitializer extends InitializerParent { @Override PluralAttributeMapping getInitializedPart(); @@ -30,11 +28,10 @@ public interface CollectionInitializer extends FetchParentAccess { return getInitializedPart().getCollectionDescriptor(); } - @Nullable PersistentCollection getCollectionInstance(); + @Nullable PersistentCollection getCollectionInstance(Data data); - @Override - default Object getInitializedInstance() { - return getCollectionInstance(); + default @Nullable PersistentCollection getCollectionInstance(RowProcessingState rowProcessingState) { + return getCollectionInstance( getData( rowProcessingState ) ); } @Override @@ -42,11 +39,8 @@ public interface CollectionInitializer extends FetchParentAccess { return true; } - @Deprecated(forRemoval = true) - @Nullable CollectionKey resolveCollectionKey(RowProcessingState rowProcessingState); - @Override - default CollectionInitializer asCollectionInitializer() { + default CollectionInitializer asCollectionInitializer() { return this; } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/LoadingCollectionEntry.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/LoadingCollectionEntry.java index 9c4a10c9f9..b82b67a0fa 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/LoadingCollectionEntry.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/LoadingCollectionEntry.java @@ -27,7 +27,7 @@ public interface LoadingCollectionEntry { /** * The initializer responsible for the loading */ - CollectionInitializer getInitializer(); + CollectionInitializer getInitializer(); /** * The collection key. diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/AbstractCollectionInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/AbstractCollectionInitializer.java index e2b1a3a0a7..3767493d64 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/AbstractCollectionInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/AbstractCollectionInitializer.java @@ -20,8 +20,8 @@ import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Initializer; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.collection.CollectionInitializer; import org.hibernate.sql.results.graph.collection.LoadingCollectionEntry; @@ -36,50 +36,45 @@ import org.checkerframework.checker.nullness.qual.Nullable; * * @author Steve Ebersole */ -public abstract class AbstractCollectionInitializer extends AbstractInitializer implements CollectionInitializer { +public abstract class AbstractCollectionInitializer + extends AbstractInitializer implements CollectionInitializer { protected final NavigablePath collectionPath; protected final PluralAttributeMapping collectionAttributeMapping; protected final boolean isResultInitializer; - protected final @Nullable InitializerParent parent; - protected final @Nullable EntityInitializer owningEntityInitializer; + protected final @Nullable InitializerParent parent; + protected final @Nullable EntityInitializer owningEntityInitializer; /** * refers to the collection's container value - which collection-key? */ protected final @Nullable DomainResultAssembler collectionKeyResultAssembler; - protected @Nullable PersistentCollection collectionInstance; - protected @Nullable Object collectionKeyValue; - protected @Nullable CollectionKey collectionKey; + public static class CollectionInitializerData extends InitializerData { + // per-row state + protected @Nullable Object collectionKeyValue; + protected @Nullable CollectionKey collectionKey; - /** - * @deprecated Use {@link #AbstractCollectionInitializer(NavigablePath, PluralAttributeMapping, InitializerParent, DomainResult, boolean, AssemblerCreationState)} instead. - */ - @Deprecated(forRemoval = true) - protected AbstractCollectionInitializer( - NavigablePath collectionPath, - PluralAttributeMapping collectionAttributeMapping, - FetchParentAccess parent, - @Nullable DomainResult collectionKeyResult, - boolean isResultInitializer, - AssemblerCreationState creationState) { - this( - collectionPath, - collectionAttributeMapping, - (InitializerParent) parent, - collectionKeyResult, - isResultInitializer, - creationState - ); + public CollectionInitializerData(RowProcessingState rowProcessingState) { + super( rowProcessingState ); + } + + public @Nullable PersistentCollection getCollectionInstance() { + return (PersistentCollection) getInstance(); + } + + public void setCollectionInstance(@Nullable PersistentCollection collectionInstance) { + setInstance( collectionInstance ); + } } protected AbstractCollectionInitializer( NavigablePath collectionPath, PluralAttributeMapping collectionAttributeMapping, - InitializerParent parent, + InitializerParent parent, @Nullable DomainResult collectionKeyResult, boolean isResultInitializer, AssemblerCreationState creationState) { + super( creationState ); this.collectionPath = collectionPath; this.collectionAttributeMapping = collectionAttributeMapping; this.isResultInitializer = isResultInitializer; @@ -87,58 +82,66 @@ public abstract class AbstractCollectionInitializer extends AbstractInitializer this.owningEntityInitializer = Initializer.findOwningEntityInitializer( parent ); this.collectionKeyResultAssembler = collectionKeyResult == null ? null - : collectionKeyResult.createResultAssembler( (InitializerParent) this, creationState ); + : collectionKeyResult.createResultAssembler( this, creationState ); } @Override - public void resolveKey() { - if ( state != State.UNINITIALIZED ) { + protected InitializerData createInitializerData(RowProcessingState rowProcessingState) { + return new CollectionInitializerData( rowProcessingState ); + } + + @Override + public void resolveKey(Data data) { + if ( data.getState() != State.UNINITIALIZED ) { // already resolved return; } - state = State.KEY_RESOLVED; - collectionKeyValue = null; + data.setState( State.KEY_RESOLVED ); + data.collectionKeyValue = null; if ( collectionKeyResultAssembler != null ) { - final Initializer initializer = collectionKeyResultAssembler.getInitializer(); + //noinspection unchecked + final Initializer initializer = (Initializer) collectionKeyResultAssembler.getInitializer(); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); if ( initializer != null ) { - initializer.resolveKey(); - if ( initializer.getState() == State.MISSING ) { - setMissing(); + final InitializerData subData = initializer.getData( rowProcessingState ); + initializer.resolveKey( subData ); + if ( subData.getState() == State.MISSING ) { + setMissing( data ); } return; } - collectionKeyValue = collectionKeyResultAssembler.assemble( rowProcessingState ); - if ( collectionKeyValue == null ) { - setMissing(); + data.collectionKeyValue = collectionKeyResultAssembler.assemble( rowProcessingState ); + if ( data.collectionKeyValue == null ) { + setMissing( data ); } } } - protected void setMissing() { - state = State.MISSING; - collectionKey = null; - collectionKeyValue = null; - collectionInstance = null; + protected void setMissing(Data data) { + data.setState( State.MISSING ); + data.collectionKey = null; + data.collectionKeyValue = null; + data.setCollectionInstance( null ); } - protected void resolveCollectionKey(RowProcessingState rowProcessingState, boolean checkPreviousRow) { - final CollectionKey oldKey = collectionKey; - final PersistentCollection oldCollectionInstance = collectionInstance; - collectionKey = null; - collectionInstance = null; + protected void resolveCollectionKey(Data data, boolean checkPreviousRow) { + final CollectionKey oldKey = data.collectionKey; + final PersistentCollection oldCollectionInstance = data.getCollectionInstance(); + data.collectionKey = null; + data.setCollectionInstance( null ); - if ( collectionKeyValue == null ) { + if ( data.collectionKeyValue == null ) { if ( collectionKeyResultAssembler == null ) { assert owningEntityInitializer != null; - collectionKeyValue = owningEntityInitializer.getEntityIdentifier(); + data.collectionKeyValue = owningEntityInitializer.getEntityIdentifier( data.getRowProcessingState() ); } else { - collectionKeyValue = collectionKeyResultAssembler.assemble( rowProcessingState ); + data.collectionKeyValue = collectionKeyResultAssembler.assemble( data.getRowProcessingState() ); } - if ( collectionKeyValue == null ) { - state = State.MISSING; - collectionKey = null; - collectionInstance = null; + if ( data.collectionKeyValue == null ) { + data.setState( State.MISSING ); + data.collectionKey = null; + data.setCollectionInstance( null ); return; } } @@ -146,96 +149,100 @@ public abstract class AbstractCollectionInitializer extends AbstractInitializer // Try to reuse the previous collection key and collection if possible if ( checkPreviousRow && oldKey != null && persister.getKeyType().isEqual( oldKey.getKey(), - collectionKeyValue + data.collectionKeyValue ) ) { - collectionKey = oldKey; - collectionInstance = oldCollectionInstance; - state = oldCollectionInstance == null ? State.MISSING : State.RESOLVED; + data.collectionKey = oldKey; + data.setCollectionInstance( oldCollectionInstance ); + data.setState( oldCollectionInstance == null ? State.MISSING : State.RESOLVED ); } else { - collectionKey = new CollectionKey( persister, collectionKeyValue ); - state = State.KEY_RESOLVED; + data.collectionKey = new CollectionKey( persister, data.collectionKeyValue ); + data.setState( State.KEY_RESOLVED ); } } - protected void resolveInstance(RowProcessingState rowProcessingState, boolean isEager) { - if ( state != State.KEY_RESOLVED ) { + protected void resolveInstance(Data data, boolean isEager) { + if ( data.getState() != State.KEY_RESOLVED ) { // already resolved return; } - resolveCollectionKey( rowProcessingState, false ); - if ( state == State.KEY_RESOLVED ) { + resolveCollectionKey( data, false ); + if ( data.getState() == State.KEY_RESOLVED ) { assert parent != null; + final RowProcessingState rowProcessingState = data.getRowProcessingState(); // We can avoid processing further if the parent is already initialized, // as the value produced by this initializer will never be used anyway. - if ( owningEntityInitializer != null && owningEntityInitializer.isEntityInitialized() ) { + if ( owningEntityInitializer != null + && owningEntityInitializer.getData( rowProcessingState ).getState() == State.INITIALIZED ) { // It doesn't matter if it's eager or lazy, the collection object can not be referred to, // so it doesn't make sense to create or initialize it - state = State.MISSING; + data.setState( State.MISSING ); return; } - state = State.RESOLVED; + data.setState( State.RESOLVED ); final SharedSessionContractImplementor session = rowProcessingState.getSession(); final PersistenceContext persistenceContext = session.getPersistenceContext(); final LoadingCollectionEntry loadingEntry = persistenceContext.getLoadContexts() - .findLoadingCollectionEntry( collectionKey ); + .findLoadingCollectionEntry( data.collectionKey ); if ( loadingEntry != null ) { - collectionInstance = loadingEntry.getCollectionInstance(); - if ( collectionInstance.getOwner() == null ) { - assert owningEntityInitializer.getTargetInstance() != null; - collectionInstance.setOwner( owningEntityInitializer.getTargetInstance() ); + data.setCollectionInstance( loadingEntry.getCollectionInstance() ); + if ( data.getCollectionInstance().getOwner() == null ) { + assert owningEntityInitializer.getTargetInstance( rowProcessingState ) != null; + data.getCollectionInstance().setOwner( owningEntityInitializer.getTargetInstance( rowProcessingState ) ); } return; } - final PersistentCollection existing = persistenceContext.getCollection( collectionKey ); + final PersistentCollection existing = persistenceContext.getCollection( data.collectionKey ); if ( existing != null ) { - collectionInstance = existing; - if ( collectionInstance.getOwner() == null ) { - assert owningEntityInitializer.getTargetInstance() != null; - collectionInstance.setOwner( owningEntityInitializer.getTargetInstance() ); + data.setCollectionInstance( existing ); + if ( data.getCollectionInstance().getOwner() == null ) { + assert owningEntityInitializer.getTargetInstance( rowProcessingState ) != null; + data.getCollectionInstance().setOwner( owningEntityInitializer.getTargetInstance( rowProcessingState ) ); } return; } final CollectionPersister collectionDescriptor = collectionAttributeMapping.getCollectionDescriptor(); final CollectionSemantics collectionSemantics = collectionDescriptor.getCollectionSemantics(); - final Object key = collectionKey.getKey(); + final Object key = data.collectionKey.getKey(); - collectionInstance = collectionSemantics.instantiateWrapper( + data.setCollectionInstance( collectionSemantics.instantiateWrapper( key, collectionDescriptor, session - ); + ) ); - assert owningEntityInitializer.getTargetInstance() != null; - collectionInstance.setOwner( owningEntityInitializer.getTargetInstance() ); + assert owningEntityInitializer.getTargetInstance( rowProcessingState ) != null; + data.getCollectionInstance().setOwner( owningEntityInitializer.getTargetInstance( rowProcessingState ) ); persistenceContext.addUninitializedCollection( collectionDescriptor, - collectionInstance, + data.getCollectionInstance(), key ); if ( isEager ) { - persistenceContext.addNonLazyCollection( collectionInstance ); + persistenceContext.addNonLazyCollection( data.getCollectionInstance() ); } if ( collectionSemantics.getCollectionClassification() == CollectionClassification.ARRAY ) { - session.getPersistenceContext().addCollectionHolder( collectionInstance ); + session.getPersistenceContext().addCollectionHolder( data.getCollectionInstance() ); } } } - public void resolveInstance(Object instance, RowProcessingState rowProcessingState, boolean isEager) { + + protected void resolveInstance(Object instance, Data data, boolean isEager) { if ( instance == null ) { - setMissing(); + setMissing( data ); } else { + final RowProcessingState rowProcessingState = data.getRowProcessingState(); final PersistenceContext persistenceContext = rowProcessingState.getSession().getPersistenceContextInternal(); final PersistentCollection persistentCollection; if ( collectionAttributeMapping.getCollectionDescriptor() @@ -249,14 +256,12 @@ public abstract class AbstractCollectionInitializer extends AbstractInitializer // resolving the collection key seems unnecessary // collectionKeyValue = persistentCollection.getKey(); // resolveCollectionKey( rowProcessingState, false ); - collectionInstance = persistentCollection; - state = State.RESOLVED; - if ( isEager && !collectionInstance.wasInitialized() ) { - persistenceContext.addNonLazyCollection( collectionInstance ); + data.setCollectionInstance( persistentCollection ); + data.setState( State.RESOLVED ); + if ( isEager && !data.getCollectionInstance().wasInitialized() ) { + persistenceContext.addNonLazyCollection( data.getCollectionInstance() ); } - if ( collectionKeyResultAssembler != null - && !rowProcessingState.isQueryCacheHit() - && rowProcessingState.getQueryOptions().isResultCachingEnabled() == Boolean.TRUE ) { + if ( collectionKeyResultAssembler != null && rowProcessingState.needsResolveState() ) { // Resolve the state of the identifier if result caching is enabled and this is not a query cache hit collectionKeyResultAssembler.resolveState( rowProcessingState ); } @@ -264,18 +269,19 @@ public abstract class AbstractCollectionInitializer extends AbstractInitializer } @Override - protected void forEachSubInitializer(BiConsumer consumer, X arg) { + protected void forEachSubInitializer(BiConsumer, RowProcessingState> consumer, InitializerData data) { if ( collectionKeyResultAssembler != null ) { - final Initializer initializer = collectionKeyResultAssembler.getInitializer(); + final Initializer initializer = collectionKeyResultAssembler.getInitializer(); if ( initializer != null ) { - consumer.accept( initializer, arg ); + consumer.accept( initializer, data.getRowProcessingState() ); } } } @Override - public @Nullable PersistentCollection getCollectionInstance() { - return state == State.UNINITIALIZED || state == State.MISSING ? null : collectionInstance; + public @Nullable PersistentCollection getCollectionInstance(Data data) { + return data.getState() == State.UNINITIALIZED || data.getState() == State.MISSING ? null : + data.getCollectionInstance(); } @Override @@ -293,20 +299,10 @@ public abstract class AbstractCollectionInitializer extends AbstractInitializer } @Override - public @Nullable FetchParentAccess getFetchParentAccess() { - return (FetchParentAccess) parent; - } - - @Override - public @Nullable InitializerParent getParent() { + public @Nullable InitializerParent getParent() { return parent; } - @Override - public Object getParentKey() { - throw new UnsupportedOperationException(); - } - @Override public boolean isPartOfKey() { // A collection can never be part of a key @@ -317,10 +313,4 @@ public abstract class AbstractCollectionInitializer extends AbstractInitializer public boolean isResultInitializer() { return isResultInitializer; } - - @Override - public @Nullable CollectionKey resolveCollectionKey(RowProcessingState rowProcessingState) { - resolveInstance(); - return collectionKey; - } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/AbstractImmediateCollectionInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/AbstractImmediateCollectionInitializer.java index f4bd56588c..60f8826280 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/AbstractImmediateCollectionInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/AbstractImmediateCollectionInitializer.java @@ -20,23 +20,19 @@ import org.hibernate.metamodel.CollectionClassification; import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.spi.NavigablePath; -import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Initializer; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.InitializerParent; -import org.hibernate.sql.results.graph.collection.CollectionLoadingLogger; import org.hibernate.sql.results.graph.collection.LoadingCollectionEntry; -import org.hibernate.sql.results.graph.entity.EntityInitializer; +import org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl; import org.hibernate.sql.results.internal.LoadingCollectionEntryImpl; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.checkerframework.checker.nullness.qual.Nullable; -import static org.hibernate.sql.results.graph.collection.CollectionLoadingLogger.COLL_LOAD_LOGGER; - /** * Base support for CollectionInitializer implementations that represent * an immediate initialization of some sort (join, select, batch, sub-select) @@ -45,54 +41,35 @@ import static org.hibernate.sql.results.graph.collection.CollectionLoadingLogger * @author Steve Ebersole * @implNote Mainly an intention contract wrt the immediacy of the fetch. */ -public abstract class AbstractImmediateCollectionInitializer extends AbstractCollectionInitializer { +public abstract class AbstractImmediateCollectionInitializer + extends AbstractCollectionInitializer { /** * refers to the rows entry in the collection. null indicates that the collection is empty */ private final @Nullable DomainResultAssembler collectionValueKeyResultAssembler; - private boolean shallowCached; + public static class ImmediateCollectionInitializerData extends CollectionInitializerData { - // per-row state + protected boolean shallowCached; - /** - * The value of the collection side of the collection key (FK). Identifies - * inclusion in the collection. Can be null to indicate that the current row - * does not contain any collection values - */ - private Object collectionValueKey; - private LoadingCollectionEntryImpl responsibility; + /** + * The value of the collection side of the collection key (FK). Identifies + * inclusion in the collection. Can be null to indicate that the current row + * does not contain any collection values + */ + protected Object collectionValueKey; + protected LoadingCollectionEntryImpl responsibility; - /** - * @deprecated Use {@link #AbstractImmediateCollectionInitializer(NavigablePath, PluralAttributeMapping, InitializerParent, LockMode, DomainResult, DomainResult, boolean, AssemblerCreationState)} instead. - */ - @Deprecated(forRemoval = true) - public AbstractImmediateCollectionInitializer( - NavigablePath collectionPath, - PluralAttributeMapping collectionAttributeMapping, - FetchParentAccess parentAccess, - LockMode lockMode, - DomainResult collectionKeyResult, - DomainResult collectionValueKeyResult, - boolean isResultInitializer, - AssemblerCreationState creationState) { - this( - collectionPath, - collectionAttributeMapping, - (InitializerParent) parentAccess, - lockMode, - collectionKeyResult, - collectionValueKeyResult, - isResultInitializer, - creationState - ); + public ImmediateCollectionInitializerData(RowProcessingState rowProcessingState) { + super( rowProcessingState ); + } } public AbstractImmediateCollectionInitializer( NavigablePath collectionPath, PluralAttributeMapping collectionAttributeMapping, - InitializerParent parent, + InitializerParent parent, LockMode lockMode, DomainResult collectionKeyResult, DomainResult collectionValueKeyResult, @@ -108,47 +85,54 @@ public abstract class AbstractImmediateCollectionInitializer extends AbstractCol ); this.collectionValueKeyResultAssembler = collectionKeyResult == collectionValueKeyResult ? null - : collectionValueKeyResult.createResultAssembler( (InitializerParent) this, creationState ); + : collectionValueKeyResult.createResultAssembler( this, creationState ); + } + + @Override + protected ImmediateCollectionInitializerData createInitializerData(RowProcessingState rowProcessingState) { + return new ImmediateCollectionInitializerData( rowProcessingState ); } protected abstract String getSimpleConcreteImplName(); @Override - protected void forEachSubInitializer(BiConsumer consumer, X arg) { - super.forEachSubInitializer( consumer, arg ); + protected void forEachSubInitializer(BiConsumer, RowProcessingState> consumer, InitializerData data) { + super.forEachSubInitializer( consumer, data ); if ( collectionValueKeyResultAssembler != null ) { - final Initializer initializer = collectionValueKeyResultAssembler.getInitializer(); + final Initializer initializer = collectionValueKeyResultAssembler.getInitializer(); if ( initializer != null ) { - consumer.accept( initializer, arg ); + consumer.accept( initializer, data.getRowProcessingState() ); } } } @Override public void startLoading(RowProcessingState rowProcessingState) { + final ImmediateCollectionInitializerData data = createInitializerData( rowProcessingState ); + rowProcessingState.setInitializerData( initializerId, data ); if ( rowProcessingState.isQueryCacheHit() && getInitializingCollectionDescriptor().useShallowQueryCacheLayout() ) { - shallowCached = true; + data.shallowCached = true; } - super.startLoading( rowProcessingState ); + forEachSubInitializer( Initializer::startLoading, data ); } @Override - public void resolveKey() { - if ( state != State.UNINITIALIZED ) { + public void resolveKey(Data data) { + if ( data.getState() != State.UNINITIALIZED ) { // already resolved return; } - super.resolveKey(); - collectionValueKey = null; + super.resolveKey( data ); + data.collectionValueKey = null; // Can't resolve any sub-initializers if the collection is shallow cached - if ( state != State.MISSING && !shallowCached ) { + if ( data.getState() != State.MISSING && !data.shallowCached ) { if ( collectionValueKeyResultAssembler == null ) { // A null collectionValueKeyResultAssembler means that we should use the parent key. // Since this method can only be called when the parent exists, we know the collection is not missing - resolveKeySubInitializers( rowProcessingState ); + resolveKeySubInitializers( data ); } else { - resolveCollectionContentKey( rowProcessingState ); + resolveCollectionContentKey( data ); } } } @@ -156,237 +140,175 @@ public abstract class AbstractImmediateCollectionInitializer extends AbstractCol /** * Returns whether the collection value key is missing. */ - private boolean resolveCollectionContentKey(RowProcessingState rowProcessingState) { + private boolean resolveCollectionContentKey(Data data) { assert collectionValueKeyResultAssembler != null; - final Initializer initializer = collectionValueKeyResultAssembler.getInitializer(); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + //noinspection unchecked + final Initializer initializer = (Initializer) collectionValueKeyResultAssembler.getInitializer(); if ( initializer != null ) { - initializer.resolveKey(); - if ( initializer.getState() == State.MISSING ) { + InitializerData subData = initializer.getData( rowProcessingState ); + initializer.resolveKey( subData ); + if ( subData.getState() == State.MISSING ) { return true; } } else { - collectionValueKey = collectionValueKeyResultAssembler.assemble( rowProcessingState ); - if ( collectionValueKey == null ) { + data.collectionValueKey = collectionValueKeyResultAssembler.assemble( rowProcessingState ); + if ( data.collectionValueKey == null ) { return true; } } // If we get here, a collectionValueKey exists or is likely to exist, // so we need to call resolveKey on the index and element initializers of the collection // to initialize this resolved collection instance later - resolveKeySubInitializers( rowProcessingState ); + resolveKeySubInitializers( data ); return false; } - private void resolveKeySubInitializers(RowProcessingState rowProcessingState) { + private void resolveKeySubInitializers(Data data) { + final RowProcessingState rowProcessingState = data.getRowProcessingState(); final DomainResultAssembler indexAssembler = getIndexAssembler(); - final Initializer indexInitializer; + final Initializer indexInitializer; if ( indexAssembler != null && ( indexInitializer = indexAssembler.getInitializer() ) != null ) { - indexInitializer.resolveKey(); + indexInitializer.resolveKey( rowProcessingState ); } - final Initializer elementInitializer = getElementAssembler().getInitializer(); + final Initializer elementInitializer = getElementAssembler().getInitializer(); if ( elementInitializer != null ) { - elementInitializer.resolveKey(); + elementInitializer.resolveKey( rowProcessingState ); } } @Override - public void resolveInstance() { - if ( state != State.KEY_RESOLVED ) { + public void resolveInstance(Data data) { + if ( data.getState() != State.KEY_RESOLVED ) { // already resolved return; } - resolveCollectionKey( rowProcessingState, true ); - if ( state != State.KEY_RESOLVED ) { + resolveCollectionKey( data, true ); + if ( data.getState() != State.KEY_RESOLVED ) { return; } - if ( CollectionLoadingLogger.COLL_LOAD_LOGGER.isDebugEnabled() ) { - CollectionLoadingLogger.COLL_LOAD_LOGGER.debugf( - "(%s) Current row collection key : %s", - this.getClass().getSimpleName(), - LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() ) - ); - } - - if ( CollectionLoadingLogger.COLL_LOAD_LOGGER.isTraceEnabled() ) { - COLL_LOAD_LOGGER.tracef( - "(%s) Beginning Initializer#resolveInstance for collection : %s", - getSimpleConcreteImplName(), - LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() ) - ); - } - - state = State.RESOLVED; - responsibility = null; + data.setState( State.RESOLVED ); + data.responsibility = null; // determine the PersistentCollection instance to use and whether // we (this initializer) is responsible for loading its state // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // First, look for a LoadingCollectionEntry + final RowProcessingState rowProcessingState = data.getRowProcessingState(); final SharedSessionContractImplementor session = rowProcessingState.getSession(); final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); final LoadingCollectionEntry existingLoadingEntry = persistenceContext.getLoadContexts() - .findLoadingCollectionEntry( collectionKey ); + .findLoadingCollectionEntry( data.collectionKey ); final PersistentCollection existing; final PersistentCollection existingUnowned; if ( existingLoadingEntry != null ) { - collectionInstance = existingLoadingEntry.getCollectionInstance(); - - if ( CollectionLoadingLogger.COLL_LOAD_LOGGER.isDebugEnabled() ) { - COLL_LOAD_LOGGER.debugf( - "(%s) Found existing loading collection entry [%s]; using loading collection instance - %s", - getSimpleConcreteImplName(), - LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() ), - toLoggableString( collectionInstance ) - ); - } + data.setCollectionInstance( existingLoadingEntry.getCollectionInstance() ); if ( existingLoadingEntry.getInitializer() == this ) { - assert !shallowCached; + assert !data.shallowCached; // we are responsible for loading the collection values - responsibility = (LoadingCollectionEntryImpl) existingLoadingEntry; + data.responsibility = (LoadingCollectionEntryImpl) existingLoadingEntry; } else { // the entity is already being loaded elsewhere - if ( CollectionLoadingLogger.COLL_LOAD_LOGGER.isDebugEnabled() ) { - COLL_LOAD_LOGGER.debugf( - "(%s) Collection [%s] being loaded by another initializer [%s] - skipping processing", - getSimpleConcreteImplName(), - LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() ), - existingLoadingEntry.getInitializer() - ); - } - state = State.INITIALIZED; + data.setState( State.INITIALIZED ); } } - else if ( ( existing = persistenceContext.getCollection( collectionKey ) ) != null ) { - collectionInstance = existing; + else if ( ( existing = persistenceContext.getCollection( data.collectionKey ) ) != null ) { + data.setCollectionInstance( existing ); // we found the corresponding collection instance on the Session. If // it is already initialized we have nothing to do - if ( collectionInstance.wasInitialized() ) { - if ( CollectionLoadingLogger.COLL_LOAD_LOGGER.isDebugEnabled() ) { - COLL_LOAD_LOGGER.debugf( - "(%s) Found existing collection instance [%s] in Session; skipping processing - [%s]", - getSimpleConcreteImplName(), - LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() ), - toLoggableString( collectionInstance ) - ); - } - state = State.INITIALIZED; + if ( data.getCollectionInstance().wasInitialized() ) { + data.setState( State.INITIALIZED ); } - else if ( !shallowCached ) { - takeResponsibility( rowProcessingState, collectionKey ); + else if ( !data.shallowCached ) { + takeResponsibility( data ); } } - else if ( ( existingUnowned = persistenceContext.useUnownedCollection( collectionKey ) ) != null ) { - collectionInstance = existingUnowned; + else if ( ( existingUnowned = persistenceContext.useUnownedCollection( data.collectionKey ) ) != null ) { + data.setCollectionInstance( existingUnowned ); // we found the corresponding collection instance as unowned on the Session. If // it is already initialized we have nothing to do - if ( collectionInstance.wasInitialized() ) { - if ( CollectionLoadingLogger.COLL_LOAD_LOGGER.isDebugEnabled() ) { - COLL_LOAD_LOGGER.debugf( - "(%s) Found existing unowned collection instance [%s] in Session; skipping processing - [%s]", - getSimpleConcreteImplName(), - LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() ), - toLoggableString( collectionInstance ) - ); - } - state = State.INITIALIZED; + if ( data.getCollectionInstance().wasInitialized() ) { + data.setState( State.INITIALIZED ); } - else if ( !shallowCached ) { - takeResponsibility( rowProcessingState, collectionKey ); + else if ( !data.shallowCached ) { + takeResponsibility( data ); } } else { final CollectionPersister collectionDescriptor = getCollectionAttributeMapping().getCollectionDescriptor(); final CollectionSemantics collectionSemantics = collectionDescriptor.getCollectionSemantics(); - collectionInstance = collectionSemantics.instantiateWrapper( - collectionKey.getKey(), + data.setCollectionInstance( collectionSemantics.instantiateWrapper( + data.collectionKey.getKey(), getInitializingCollectionDescriptor(), session - ); - - if ( CollectionLoadingLogger.COLL_LOAD_LOGGER.isDebugEnabled() ) { - COLL_LOAD_LOGGER.debugf( - "(%s) Created new collection wrapper [%s] : %s", - getSimpleConcreteImplName(), - LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() ), - toLoggableString( collectionInstance ) - ); - } + ) ); if ( owningEntityInitializer != null ) { - assert owningEntityInitializer.getTargetInstance() != null; - collectionInstance.setOwner( owningEntityInitializer.getTargetInstance() ); + assert owningEntityInitializer.getTargetInstance( rowProcessingState ) != null; + data.getCollectionInstance().setOwner( owningEntityInitializer.getTargetInstance( rowProcessingState ) ); } persistenceContext.addUninitializedCollection( collectionDescriptor, - collectionInstance, - collectionKey.getKey() + data.getCollectionInstance(), + data.collectionKey.getKey() ); - if ( !shallowCached ) { - takeResponsibility( rowProcessingState, collectionKey ); + if ( !data.shallowCached ) { + takeResponsibility( data ); } } - if ( responsibility != null ) { - if ( CollectionLoadingLogger.COLL_LOAD_LOGGER.isDebugEnabled() ) { - COLL_LOAD_LOGGER.debugf( - "(%s) Responsible for loading collection [%s] : %s", - getSimpleConcreteImplName(), - LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() ), - toLoggableString( collectionInstance ) - ); - } - } - if ( shallowCached ) { - assert responsibility == null; - initializeShallowCached( rowProcessingState ); + if ( data.shallowCached ) { + assert data.responsibility == null; + initializeShallowCached( data ); } } - protected void initializeShallowCached(RowProcessingState rowProcessingState) { - assert shallowCached; - final PersistenceContext persistenceContext = rowProcessingState.getSession() + protected void initializeShallowCached(Data data) { + assert data.shallowCached; + final PersistenceContext persistenceContext = data.getRowProcessingState().getSession() .getPersistenceContextInternal(); // If this is a query cache hit with the shallow query cache layout, // we have to lazy load the collection instead - collectionInstance.forceInitialization(); + data.getCollectionInstance().forceInitialization(); if ( collectionAttributeMapping.getCollectionDescriptor() .getCollectionSemantics() .getCollectionClassification() == CollectionClassification.ARRAY ) { - persistenceContext.addCollectionHolder( collectionInstance ); + persistenceContext.addCollectionHolder( data.getCollectionInstance() ); } - state = State.INITIALIZED; - initializeSubInstancesFromParent( rowProcessingState ); + data.setState( State.INITIALIZED ); + initializeSubInstancesFromParent( data ); } @Override - protected void setMissing() { - super.setMissing(); - collectionValueKey = null; - responsibility = null; + protected void setMissing(Data data) { + super.setMissing( data ); + data.collectionValueKey = null; + data.responsibility = null; } @Override - public void resolveInstance(Object instance) { - assert state == State.UNINITIALIZED; + public void resolveInstance(Object instance, Data data) { + assert data.getState() == State.UNINITIALIZED || instance == data.getCollectionInstance(); if ( instance == null ) { - setMissing(); + setMissing( data ); return; } + final RowProcessingState rowProcessingState = data.getRowProcessingState(); // Check if the given instance is different from the previous row state to avoid creating CollectionKey - if ( collectionInstance != instance ) { + if ( data.getCollectionInstance() != instance ) { final PersistenceContext persistenceContext = rowProcessingState.getSession().getPersistenceContextInternal(); final PersistentCollection persistentCollection; if ( collectionAttributeMapping.getCollectionDescriptor() @@ -397,21 +319,21 @@ public abstract class AbstractImmediateCollectionInitializer extends AbstractCol else { persistentCollection = (PersistentCollection) instance; } - collectionKeyValue = persistentCollection.getKey(); - resolveCollectionKey( rowProcessingState, false ); - collectionInstance = persistentCollection; - responsibility = null; + data.collectionKeyValue = persistentCollection.getKey(); + resolveCollectionKey( data, false ); + data.setCollectionInstance( persistentCollection ); + data.responsibility = null; } - collectionValueKey = null; - if ( collectionInstance.wasInitialized() ) { - state = State.INITIALIZED; - if ( shallowCached ) { - initializeShallowCached( rowProcessingState ); + data.collectionValueKey = null; + if ( data.getCollectionInstance().wasInitialized() ) { + data.setState( State.INITIALIZED ); + if ( data.shallowCached ) { + initializeShallowCached( data ); } else { - resolveInstanceSubInitializers( rowProcessingState ); + resolveInstanceSubInitializers( data ); } - if ( !rowProcessingState.isQueryCacheHit() && rowProcessingState.getQueryOptions().isResultCachingEnabled() == Boolean.TRUE ) { + if ( rowProcessingState.needsResolveState() ) { // Resolve the state of the identifier if result caching is enabled and this is not a query cache hit if ( collectionKeyResultAssembler != null ) { collectionKeyResultAssembler.resolveState( rowProcessingState ); @@ -425,42 +347,33 @@ public abstract class AbstractImmediateCollectionInitializer extends AbstractCol } } else { - if ( shallowCached ) { - state = State.INITIALIZED; - initializeShallowCached( rowProcessingState ); + if ( data.shallowCached ) { + data.setState( State.INITIALIZED ); + initializeShallowCached( data ); } else { - state = State.RESOLVED; + data.setState( State.RESOLVED ); final boolean rowContainsCollectionContent; if ( collectionValueKeyResultAssembler != null ) { - rowContainsCollectionContent = resolveCollectionContentKey( rowProcessingState ); + rowContainsCollectionContent = resolveCollectionContentKey( data ); } else { rowContainsCollectionContent = true; } - if ( responsibility == null ) { + if ( data.responsibility == null ) { final LoadingCollectionEntry existingLoadingEntry = rowProcessingState.getSession() .getPersistenceContextInternal() .getLoadContexts() - .findLoadingCollectionEntry( collectionKey ); + .findLoadingCollectionEntry( data.collectionKey ); if ( existingLoadingEntry != null ) { if ( existingLoadingEntry.getInitializer() == this ) { // we are responsible for loading the collection values - responsibility = (LoadingCollectionEntryImpl) existingLoadingEntry; + data.responsibility = (LoadingCollectionEntryImpl) existingLoadingEntry; } else { // the collection is already being loaded elsewhere - if ( CollectionLoadingLogger.COLL_LOAD_LOGGER.isDebugEnabled() ) { - COLL_LOAD_LOGGER.debugf( - "(%s) Collection [%s] being loaded by another initializer [%s] - skipping processing", - getSimpleConcreteImplName(), - LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() ), - existingLoadingEntry.getInitializer() - ); - } - state = State.INITIALIZED; - if ( rowContainsCollectionContent && !rowProcessingState.isQueryCacheHit() - && rowProcessingState.getQueryOptions().isResultCachingEnabled() == Boolean.TRUE + data.setState( State.INITIALIZED ); + if ( rowContainsCollectionContent && rowProcessingState.needsResolveState() && !getInitializingCollectionDescriptor().useShallowQueryCacheLayout() ) { // Resolve the state of the content if result caching is enabled and this is not a query cache hit // and the collection doesn't use a shallow query cache layout @@ -469,14 +382,14 @@ public abstract class AbstractImmediateCollectionInitializer extends AbstractCol } } else { - takeResponsibility( rowProcessingState, collectionKey ); + takeResponsibility( data ); } } } } } - protected abstract void resolveInstanceSubInitializers(RowProcessingState rowProcessingState); + protected abstract void resolveInstanceSubInitializers(Data data); private void resolveCollectionContentState(RowProcessingState rowProcessingState) { final DomainResultAssembler indexAssembler = getIndexAssembler(); @@ -496,56 +409,48 @@ public abstract class AbstractImmediateCollectionInitializer extends AbstractCol : collectionInstance.getClass().getName() + "@" + System.identityHashCode( collectionInstance ); } - protected void takeResponsibility(RowProcessingState rowProcessingState, CollectionKey collectionKey) { - responsibility = new LoadingCollectionEntryImpl( + protected void takeResponsibility(Data data) { + data.responsibility = new LoadingCollectionEntryImpl( getCollectionAttributeMapping().getCollectionDescriptor(), this, - collectionKey.getKey(), - collectionInstance + data.collectionKey.getKey(), + data.getCollectionInstance() ); - rowProcessingState.getJdbcValuesSourceProcessingState().registerLoadingCollection( - collectionKey, - responsibility + data.getRowProcessingState().getJdbcValuesSourceProcessingState().registerLoadingCollection( + data.collectionKey, + data.responsibility ); } @Override - public void initializeInstance() { - if ( state != State.RESOLVED || responsibility == null ) { + public void initializeInstance(Data data) { + if ( data.getState() != State.RESOLVED || data.responsibility == null ) { return; } - state = State.INITIALIZED; + data.setState( State.INITIALIZED ); - if ( collectionValueKey == null && collectionValueKeyResultAssembler != null ) { - final Initializer initializer = collectionValueKeyResultAssembler.getInitializer(); + final RowProcessingState initializerRowProcessingState = data.getRowProcessingState(); + if ( data.collectionValueKey == null && collectionValueKeyResultAssembler != null ) { + final Initializer initializer = collectionValueKeyResultAssembler.getInitializer(); if ( initializer != null ) { - collectionValueKey = collectionValueKeyResultAssembler.assemble( rowProcessingState ); + data.collectionValueKey = collectionValueKeyResultAssembler.assemble( initializerRowProcessingState ); } } // the RHS key value of the association - determines if the row contains an element of the initializing collection - if ( collectionValueKeyResultAssembler == null || collectionValueKey != null ) { + if ( collectionValueKeyResultAssembler == null || data.collectionValueKey != null ) { // the row contains an element in the collection... - if ( CollectionLoadingLogger.COLL_LOAD_LOGGER.isDebugEnabled() ) { - COLL_LOAD_LOGGER.debugf( - "(%s) Reading element from row for collection [%s] -> %s", - getSimpleConcreteImplName(), - LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() ), - toLoggableString( collectionInstance ) - ); - } - - responsibility.load( - loadingState -> readCollectionRow( collectionKey, loadingState, rowProcessingState ) + data.responsibility.load( + loadingState -> readCollectionRow( data.collectionKey, loadingState, initializerRowProcessingState ) ); } } @Override - public void initializeInstanceFromParent(Object parentInstance) { - collectionInstance = (PersistentCollection) getInitializedPart().getValue( parentInstance ); - state = State.INITIALIZED; - initializeSubInstancesFromParent( rowProcessingState ); + public void initializeInstanceFromParent(Object parentInstance, Data data) { + data.setCollectionInstance( (PersistentCollection) getInitializedPart().getValue( parentInstance ) ); + data.setState( State.INITIALIZED ); + initializeSubInstancesFromParent( data ); } protected abstract void readCollectionRow( @@ -553,16 +458,15 @@ public abstract class AbstractImmediateCollectionInitializer extends AbstractCol List loadingState, RowProcessingState rowProcessingState); - protected abstract void initializeSubInstancesFromParent(RowProcessingState rowProcessingState); + protected abstract void initializeSubInstancesFromParent(Data data); public abstract @Nullable DomainResultAssembler getIndexAssembler(); public abstract DomainResultAssembler getElementAssembler(); @Override - public void endLoading(ExecutionContext executionContext) { - super.endLoading( executionContext ); - shallowCached = false; + public void endLoading(Data data) { + super.endLoading( data ); + data.shallowCached = false; } - } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/ArrayInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/ArrayInitializer.java index 02f8ad7f9d..e32b3f4ca7 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/ArrayInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/ArrayInitializer.java @@ -21,8 +21,8 @@ import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Fetch; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Initializer; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; @@ -31,7 +31,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; /** * @author Chris Cranford */ -public class ArrayInitializer extends AbstractImmediateCollectionInitializer { +public class ArrayInitializer extends AbstractImmediateCollectionInitializer { private static final String CONCRETE_NAME = ArrayInitializer.class.getSimpleName(); private final DomainResultAssembler listIndexAssembler; @@ -39,39 +39,10 @@ public class ArrayInitializer extends AbstractImmediateCollectionInitializer { private final int indexBase; - /** - * @deprecated Use {@link #ArrayInitializer(NavigablePath, PluralAttributeMapping, InitializerParent, LockMode, DomainResult, DomainResult, boolean, AssemblerCreationState, Fetch, Fetch)} instead. - */ - @Deprecated(forRemoval = true) public ArrayInitializer( NavigablePath navigablePath, PluralAttributeMapping arrayDescriptor, - FetchParentAccess parentAccess, - LockMode lockMode, - DomainResult collectionKeyResult, - DomainResult collectionValueKeyResult, - Fetch listIndexFetch, - Fetch elementFetch, - boolean isResultInitializer, - AssemblerCreationState creationState) { - this( - navigablePath, - arrayDescriptor, - (InitializerParent) parentAccess, - lockMode, - collectionKeyResult, - collectionValueKeyResult, - isResultInitializer, - creationState, - listIndexFetch, - elementFetch - ); - } - - public ArrayInitializer( - NavigablePath navigablePath, - PluralAttributeMapping arrayDescriptor, - InitializerParent parent, + InitializerParent parent, LockMode lockMode, DomainResult collectionKeyResult, DomainResult collectionValueKeyResult, @@ -90,8 +61,8 @@ public class ArrayInitializer extends AbstractImmediateCollectionInitializer { creationState ); //noinspection unchecked - this.listIndexAssembler = (DomainResultAssembler) listIndexFetch.createAssembler( (InitializerParent) this, creationState ); - this.elementAssembler = elementFetch.createAssembler( (InitializerParent) this, creationState ); + this.listIndexAssembler = (DomainResultAssembler) listIndexFetch.createAssembler( this, creationState ); + this.elementAssembler = elementFetch.createAssembler( this, creationState ); this.indexBase = getCollectionAttributeMapping().getIndexMetadata().getListIndexBase(); } @@ -101,17 +72,17 @@ public class ArrayInitializer extends AbstractImmediateCollectionInitializer { } @Override - protected void forEachSubInitializer(BiConsumer consumer, X arg) { - super.forEachSubInitializer( consumer, arg ); - final Initializer initializer = elementAssembler.getInitializer(); + protected void forEachSubInitializer(BiConsumer, RowProcessingState> consumer, InitializerData data) { + super.forEachSubInitializer( consumer, data ); + final Initializer initializer = elementAssembler.getInitializer(); if ( initializer != null ) { - consumer.accept( initializer, arg ); + consumer.accept( initializer, data.getRowProcessingState() ); } } @Override - public @Nullable PersistentArrayHolder getCollectionInstance() { - return (PersistentArrayHolder) super.getCollectionInstance(); + public @Nullable PersistentArrayHolder getCollectionInstance(ImmediateCollectionInitializerData data) { + return (PersistentArrayHolder) super.getCollectionInstance( data ); } @Override @@ -143,34 +114,36 @@ public class ArrayInitializer extends AbstractImmediateCollectionInitializer { } @Override - public void initializeInstanceFromParent(Object parentInstance) { + public void initializeInstanceFromParent(Object parentInstance, ImmediateCollectionInitializerData data) { final Object[] array = (Object[]) getInitializedPart().getValue( parentInstance ); assert array != null; - collectionInstance = rowProcessingState.getSession() + data.setCollectionInstance( data.getRowProcessingState().getSession() .getPersistenceContextInternal() - .getCollectionHolder( array ); - state = State.INITIALIZED; - initializeSubInstancesFromParent( rowProcessingState ); + .getCollectionHolder( array ) ); + data.setState( State.INITIALIZED ); + initializeSubInstancesFromParent( data ); } @Override - protected void initializeSubInstancesFromParent(RowProcessingState rowProcessingState) { - final Initializer initializer = elementAssembler.getInitializer(); + protected void initializeSubInstancesFromParent(ImmediateCollectionInitializerData data) { + final Initializer initializer = elementAssembler.getInitializer(); if ( initializer != null ) { - final Iterator iter = getCollectionInstance().elements(); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final Iterator iter = getCollectionInstance( data ).elements(); while ( iter.hasNext() ) { - initializer.initializeInstanceFromParent( iter.next() ); + initializer.initializeInstanceFromParent( iter.next(), rowProcessingState ); } } } @Override - protected void resolveInstanceSubInitializers(RowProcessingState rowProcessingState) { - final Initializer initializer = elementAssembler.getInitializer(); + protected void resolveInstanceSubInitializers(ImmediateCollectionInitializerData data) { + final Initializer initializer = elementAssembler.getInitializer(); if ( initializer != null ) { - final Iterator iter = getCollectionInstance().elements(); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final Iterator iter = getCollectionInstance( data ).elements(); while ( iter.hasNext() ) { - initializer.resolveInstance( iter.next() ); + initializer.resolveInstance( iter.next(), rowProcessingState ); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/ArrayInitializerProducer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/ArrayInitializerProducer.java index 576fb41b8d..f2994fef7d 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/ArrayInitializerProducer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/ArrayInitializerProducer.java @@ -12,9 +12,7 @@ import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; -import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Fetch; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.collection.CollectionInitializer; @@ -36,22 +34,10 @@ public class ArrayInitializerProducer implements CollectionInitializerProducer { } @Override - public CollectionInitializer produceInitializer( - NavigablePath navigablePath, - PluralAttributeMapping attributeMapping, - FetchParentAccess parentAccess, - LockMode lockMode, - DomainResultAssembler collectionKeyAssembler, - DomainResultAssembler collectionValueKeyAssembler, - AssemblerCreationState creationState) { - throw new UnsupportedOperationException( "Use the non-deprecated method variant instead." ); - } - - @Override - public CollectionInitializer produceInitializer( + public CollectionInitializer produceInitializer( NavigablePath navigablePath, PluralAttributeMapping attribute, - InitializerParent parent, + InitializerParent parent, LockMode lockMode, DomainResult collectionKeyResult, DomainResult collectionValueKeyResult, diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/BagInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/BagInitializer.java index 235cb2be3f..03e605eb3a 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/BagInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/BagInitializer.java @@ -21,8 +21,8 @@ import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Fetch; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Initializer; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; @@ -34,45 +34,16 @@ import org.checkerframework.checker.nullness.qual.Nullable; * * @author Steve Ebersole */ -public class BagInitializer extends AbstractImmediateCollectionInitializer { +public class BagInitializer extends AbstractImmediateCollectionInitializer { private static final String CONCRETE_NAME = BagInitializer.class.getSimpleName(); private final DomainResultAssembler elementAssembler; private final DomainResultAssembler collectionIdAssembler; - /** - * @deprecated Use {@link #BagInitializer(NavigablePath, PluralAttributeMapping, InitializerParent, LockMode, DomainResult, DomainResult, boolean, AssemblerCreationState, Fetch, Fetch)} instead. - */ - @Deprecated(forRemoval = true) - public BagInitializer( - PluralAttributeMapping bagDescriptor, - FetchParentAccess parentAccess, - NavigablePath navigablePath, - LockMode lockMode, - DomainResult collectionKeyResult, - DomainResult collectionValueKeyResult, - Fetch elementFetch, - @Nullable Fetch collectionIdFetch, - boolean isResultInitializer, - AssemblerCreationState creationState) { - this( - navigablePath, - bagDescriptor, - (InitializerParent) parentAccess, - lockMode, - collectionKeyResult, - collectionValueKeyResult, - isResultInitializer, - creationState, - elementFetch, - collectionIdFetch - ); - } - public BagInitializer( NavigablePath navigablePath, PluralAttributeMapping bagDescriptor, - InitializerParent parent, + InitializerParent parent, LockMode lockMode, DomainResult collectionKeyResult, DomainResult collectionValueKeyResult, @@ -90,10 +61,10 @@ public class BagInitializer extends AbstractImmediateCollectionInitializer { isResultInitializer, creationState ); - this.elementAssembler = elementFetch.createAssembler( (InitializerParent) this, creationState ); + this.elementAssembler = elementFetch.createAssembler( this, creationState ); this.collectionIdAssembler = collectionIdFetch == null ? null - : collectionIdFetch.createAssembler( (InitializerParent) this, creationState ); + : collectionIdFetch.createAssembler( this, creationState ); } @Override @@ -102,11 +73,11 @@ public class BagInitializer extends AbstractImmediateCollectionInitializer { } @Override - protected void forEachSubInitializer(BiConsumer consumer, X arg) { - super.forEachSubInitializer( consumer, arg ); - final Initializer initializer = elementAssembler.getInitializer(); + protected void forEachSubInitializer(BiConsumer, RowProcessingState> consumer, InitializerData data) { + super.forEachSubInitializer( consumer, data ); + final Initializer initializer = elementAssembler.getInitializer(); if ( initializer != null ) { - consumer.accept( initializer, arg ); + consumer.accept( initializer, data.getRowProcessingState() ); } } @@ -138,38 +109,40 @@ public class BagInitializer extends AbstractImmediateCollectionInitializer { } @Override - protected void initializeSubInstancesFromParent(RowProcessingState rowProcessingState) { - final Initializer initializer = elementAssembler.getInitializer(); + protected void initializeSubInstancesFromParent(ImmediateCollectionInitializerData data) { + final Initializer initializer = elementAssembler.getInitializer(); if ( initializer != null ) { - final PersistentCollection persistentCollection = getCollectionInstance(); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final PersistentCollection persistentCollection = getCollectionInstance( data ); assert persistentCollection != null; if ( persistentCollection instanceof PersistentBag ) { for ( Object element : ( (PersistentBag) persistentCollection ) ) { - initializer.initializeInstanceFromParent( element ); + initializer.initializeInstanceFromParent( element, rowProcessingState ); } } else { for ( Object element : ( (PersistentIdentifierBag) persistentCollection ) ) { - initializer.initializeInstanceFromParent( element ); + initializer.initializeInstanceFromParent( element, rowProcessingState ); } } } } @Override - protected void resolveInstanceSubInitializers(RowProcessingState rowProcessingState) { - final Initializer initializer = elementAssembler.getInitializer(); + protected void resolveInstanceSubInitializers(ImmediateCollectionInitializerData data) { + final Initializer initializer = elementAssembler.getInitializer(); if ( initializer != null ) { - final PersistentCollection persistentCollection = getCollectionInstance(); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final PersistentCollection persistentCollection = getCollectionInstance( data ); assert persistentCollection != null; if ( persistentCollection instanceof PersistentBag ) { for ( Object element : ( (PersistentBag) persistentCollection ) ) { - initializer.resolveInstance( element ); + initializer.resolveInstance( element, rowProcessingState ); } } else { for ( Object element : ( (PersistentIdentifierBag) persistentCollection ) ) { - initializer.resolveInstance( element ); + initializer.resolveInstance( element, rowProcessingState ); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/BagInitializerProducer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/BagInitializerProducer.java index 103b7fd80c..a32786cbf1 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/BagInitializerProducer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/BagInitializerProducer.java @@ -12,9 +12,7 @@ import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; -import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Fetch; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.collection.CollectionInitializer; @@ -48,22 +46,10 @@ public class BagInitializerProducer implements CollectionInitializerProducer { } @Override - public CollectionInitializer produceInitializer( - NavigablePath navigablePath, - PluralAttributeMapping attributeMapping, - FetchParentAccess parentAccess, - LockMode lockMode, - DomainResultAssembler collectionKeyAssembler, - DomainResultAssembler collectionValueKeyAssembler, - AssemblerCreationState creationState) { - throw new UnsupportedOperationException( "Use the non-deprecated method variant instead." ); - } - - @Override - public CollectionInitializer produceInitializer( + public CollectionInitializer produceInitializer( NavigablePath navigablePath, PluralAttributeMapping attribute, - InitializerParent parent, + InitializerParent parent, LockMode lockMode, DomainResult collectionKeyResult, DomainResult collectionValueKeyResult, diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/CollectionAssembler.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/CollectionAssembler.java index 6cdf5ffb4b..4fd1fd66c2 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/CollectionAssembler.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/CollectionAssembler.java @@ -14,7 +14,6 @@ import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.collection.CollectionInitializer; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.descriptor.java.JavaType; @@ -24,19 +23,18 @@ import org.hibernate.type.descriptor.java.JavaType; public class CollectionAssembler implements DomainResultAssembler { private final PluralAttributeMapping fetchedMapping; - protected final CollectionInitializer initializer; + protected final CollectionInitializer initializer; - public CollectionAssembler(PluralAttributeMapping fetchedMapping, CollectionInitializer initializer) { + public CollectionAssembler(PluralAttributeMapping fetchedMapping, CollectionInitializer initializer) { this.fetchedMapping = fetchedMapping; this.initializer = initializer; } @Override - public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) { - assert initializer.getState() != Initializer.State.UNINITIALIZED - && initializer.getState() != Initializer.State.KEY_RESOLVED; -// initializer.resolve( rowProcessingState ); - PersistentCollection collectionInstance = initializer.getCollectionInstance(); + public Object assemble(RowProcessingState rowProcessingState) { + assert initializer.getData( rowProcessingState ).getState() != Initializer.State.UNINITIALIZED + && initializer.getData( rowProcessingState ).getState() != Initializer.State.KEY_RESOLVED; + PersistentCollection collectionInstance = initializer.getCollectionInstance( rowProcessingState ); if ( collectionInstance instanceof PersistentArrayHolder ) { return collectionInstance.getValue(); } @@ -49,13 +47,13 @@ public class CollectionAssembler implements DomainResultAssembler { } @Override - public CollectionInitializer getInitializer() { + public CollectionInitializer getInitializer() { return initializer; } @Override public void resolveState(RowProcessingState rowProcessingState) { - initializer.resolveInstance(); + initializer.resolveInstance( rowProcessingState ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/CollectionDomainResult.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/CollectionDomainResult.java index 905fdfa305..ff4c8c52a1 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/CollectionDomainResult.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/CollectionDomainResult.java @@ -19,7 +19,6 @@ import org.hibernate.sql.results.graph.DomainResultAssembler; 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.FetchParentAccess; import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.graph.FetchableContainer; import org.hibernate.sql.results.graph.InitializerParent; @@ -89,13 +88,6 @@ public class CollectionDomainResult implements DomainResult, CollectionResultGra return loadingAttribute.getJavaType(); } - @Override - public DomainResultAssembler createResultAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createResultAssembler( (InitializerParent) parentAccess, creationState ); - } - @Override public DomainResultAssembler createResultAssembler( InitializerParent parent, @@ -104,15 +96,15 @@ public class CollectionDomainResult implements DomainResult, CollectionResultGra } @Override - public CollectionInitializer createInitializer( + public CollectionInitializer createInitializer( CollectionDomainResult resultGraphNode, - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return resultGraphNode.createInitializer( parent, creationState ); } @Override - public CollectionInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { + public CollectionInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { return initializerProducer.produceInitializer( loadingPath, loadingAttribute, diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/CollectionFetch.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/CollectionFetch.java index a297ea2a8e..85b099f63e 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/CollectionFetch.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/CollectionFetch.java @@ -12,7 +12,6 @@ import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Fetch; import org.hibernate.sql.results.graph.FetchParent; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.InitializerParent; @@ -84,14 +83,7 @@ public abstract class CollectionFetch implements FetchParent, Fetch, Initializer @Override public DomainResultAssembler createAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createAssembler( (InitializerParent) parentAccess, creationState ); - } - - @Override - public DomainResultAssembler createAssembler( - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return new CollectionAssembler( getFetchedMapping(), @@ -100,9 +92,9 @@ public abstract class CollectionFetch implements FetchParent, Fetch, Initializer } @Override - public Initializer createInitializer( + public Initializer createInitializer( CollectionFetch resultGraphNode, - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return resultGraphNode.createInitializer( parent, creationState ); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/DelayedCollectionFetch.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/DelayedCollectionFetch.java index cba4017d90..83b09319d1 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/DelayedCollectionFetch.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/DelayedCollectionFetch.java @@ -15,7 +15,6 @@ import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.FetchParent; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.collection.CollectionInitializer; import org.hibernate.type.descriptor.java.JavaType; @@ -41,14 +40,7 @@ public class DelayedCollectionFetch extends CollectionFetch { @Override public DomainResultAssembler createAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createAssembler( (InitializerParent) parentAccess, creationState ); - } - - @Override - public DomainResultAssembler createAssembler( - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { // lazy attribute if ( unfetched ) { @@ -59,7 +51,7 @@ public class DelayedCollectionFetch extends CollectionFetch { } } - public CollectionInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { + public CollectionInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { return new DelayedCollectionInitializer( getNavigablePath(), getFetchedMapping(), diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/DelayedCollectionInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/DelayedCollectionInitializer.java index fd22d38b27..191195a7fe 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/DelayedCollectionInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/DelayedCollectionInitializer.java @@ -11,44 +11,30 @@ import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.InitializerParent; /** * @author Steve Ebersole */ -public class DelayedCollectionInitializer extends AbstractCollectionInitializer { - - /** - * @deprecated Use {@link #DelayedCollectionInitializer(NavigablePath, PluralAttributeMapping, InitializerParent, DomainResult, AssemblerCreationState)} instead. - */ - @Deprecated(forRemoval = true) - public DelayedCollectionInitializer( - NavigablePath fetchedPath, - PluralAttributeMapping fetchedMapping, - FetchParentAccess parentAccess, - DomainResult collectionKeyResult, - AssemblerCreationState creationState) { - super( fetchedPath, fetchedMapping, parentAccess, collectionKeyResult, false, creationState ); - } +public class DelayedCollectionInitializer extends AbstractCollectionInitializer { public DelayedCollectionInitializer( NavigablePath fetchedPath, PluralAttributeMapping fetchedMapping, - InitializerParent parent, + InitializerParent parent, DomainResult collectionKeyResult, AssemblerCreationState creationState) { super( fetchedPath, fetchedMapping, parent, collectionKeyResult, false, creationState ); } @Override - public void resolveInstance() { - resolveInstance( rowProcessingState, false ); + public void resolveInstance(CollectionInitializerData data) { + resolveInstance( data, false ); } @Override - public void resolveInstance(Object instance) { - resolveInstance( instance, rowProcessingState, false ); + public void resolveInstance(Object instance, CollectionInitializerData data) { + resolveInstance( instance, data, false ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/EagerCollectionFetch.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/EagerCollectionFetch.java index ec8157b3d9..40126cc62f 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/EagerCollectionFetch.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/EagerCollectionFetch.java @@ -153,7 +153,7 @@ public class EagerCollectionFetch extends CollectionFetch { } @Override - public CollectionInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { + public CollectionInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { return initializerProducer.produceInitializer( getNavigablePath(), getFetchedMapping(), diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/ListInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/ListInitializer.java index 2d07ad7b2f..d56febda40 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/ListInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/ListInitializer.java @@ -20,8 +20,8 @@ import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Fetch; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Initializer; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; @@ -32,7 +32,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; * * @author Steve Ebersole */ -public class ListInitializer extends AbstractImmediateCollectionInitializer { +public class ListInitializer extends AbstractImmediateCollectionInitializer { private static final String CONCRETE_NAME = ListInitializer.class.getSimpleName(); private final DomainResultAssembler listIndexAssembler; @@ -40,37 +40,10 @@ public class ListInitializer extends AbstractImmediateCollectionInitializer { private final int listIndexBase; - /** - * @deprecated Use {@link #ListInitializer(NavigablePath, PluralAttributeMapping, InitializerParent, LockMode, DomainResult, DomainResult, boolean, AssemblerCreationState, Fetch, Fetch)} instead. - */ - @Deprecated(forRemoval = true) public ListInitializer( NavigablePath navigablePath, PluralAttributeMapping attributeMapping, - FetchParentAccess parentAccess, - LockMode lockMode, - DomainResult collectionKeyResult, - DomainResult collectionValueKeyResult, - Fetch listIndexFetch, - Fetch elementFetch, - boolean isResultInitializer, - AssemblerCreationState creationState) { - this( - navigablePath, - attributeMapping, - (InitializerParent) parentAccess, - lockMode, - collectionKeyResult, - collectionValueKeyResult, - isResultInitializer, creationState, listIndexFetch, - elementFetch - ); - } - - public ListInitializer( - NavigablePath navigablePath, - PluralAttributeMapping attributeMapping, - InitializerParent parent, + InitializerParent parent, LockMode lockMode, DomainResult collectionKeyResult, DomainResult collectionValueKeyResult, @@ -89,8 +62,8 @@ public class ListInitializer extends AbstractImmediateCollectionInitializer { creationState ); //noinspection unchecked - this.listIndexAssembler = (DomainResultAssembler) listIndexFetch.createAssembler( (InitializerParent) this, creationState ); - this.elementAssembler = elementFetch.createAssembler( (InitializerParent) this, creationState ); + this.listIndexAssembler = (DomainResultAssembler) listIndexFetch.createAssembler( this, creationState ); + this.elementAssembler = elementFetch.createAssembler( this, creationState ); this.listIndexBase = attributeMapping.getIndexMetadata().getListIndexBase(); } @@ -100,17 +73,17 @@ public class ListInitializer extends AbstractImmediateCollectionInitializer { } @Override - protected void forEachSubInitializer(BiConsumer consumer, X arg) { - super.forEachSubInitializer( consumer, arg ); - final Initializer initializer = elementAssembler.getInitializer(); + protected void forEachSubInitializer(BiConsumer, RowProcessingState> consumer, InitializerData data) { + super.forEachSubInitializer( consumer, data ); + final Initializer initializer = elementAssembler.getInitializer(); if ( initializer != null ) { - consumer.accept( initializer, arg ); + consumer.accept( initializer, data.getRowProcessingState() ); } } @Override - public @Nullable PersistentList getCollectionInstance() { - return (PersistentList) super.getCollectionInstance(); + public @Nullable PersistentList getCollectionInstance(ImmediateCollectionInitializerData data) { + return (PersistentList) super.getCollectionInstance( data ); } @Override @@ -142,25 +115,27 @@ public class ListInitializer extends AbstractImmediateCollectionInitializer { } @Override - protected void initializeSubInstancesFromParent(RowProcessingState rowProcessingState) { - final Initializer initializer = elementAssembler.getInitializer(); + protected void initializeSubInstancesFromParent(ImmediateCollectionInitializerData data) { + final Initializer initializer = elementAssembler.getInitializer(); if ( initializer != null ) { - final PersistentList list = getCollectionInstance(); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final PersistentList list = getCollectionInstance( data ); assert list != null; for ( Object element : list ) { - initializer.initializeInstanceFromParent( element ); + initializer.initializeInstanceFromParent( element, rowProcessingState ); } } } @Override - protected void resolveInstanceSubInitializers(RowProcessingState rowProcessingState) { - final Initializer initializer = elementAssembler.getInitializer(); + protected void resolveInstanceSubInitializers(ImmediateCollectionInitializerData data) { + final Initializer initializer = elementAssembler.getInitializer(); if ( initializer != null ) { - final PersistentList list = getCollectionInstance(); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final PersistentList list = getCollectionInstance( data ); assert list != null; for ( Object element : list ) { - initializer.resolveInstance( element ); + initializer.resolveInstance( element, rowProcessingState ); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/ListInitializerProducer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/ListInitializerProducer.java index 25ec7405ea..be73e877b6 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/ListInitializerProducer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/ListInitializerProducer.java @@ -12,9 +12,7 @@ import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; -import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Fetch; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.collection.CollectionInitializer; @@ -36,22 +34,10 @@ public class ListInitializerProducer implements CollectionInitializerProducer { } @Override - public CollectionInitializer produceInitializer( - NavigablePath navigablePath, - PluralAttributeMapping attributeMapping, - FetchParentAccess parentAccess, - LockMode lockMode, - DomainResultAssembler collectionKeyAssembler, - DomainResultAssembler collectionValueKeyAssembler, - AssemblerCreationState creationState) { - throw new UnsupportedOperationException( "Use the non-deprecated method variant instead." ); - } - - @Override - public CollectionInitializer produceInitializer( + public CollectionInitializer produceInitializer( NavigablePath navigablePath, PluralAttributeMapping attribute, - InitializerParent parent, + InitializerParent parent, LockMode lockMode, DomainResult collectionKeyResult, DomainResult collectionValueKeyResult, diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/MapInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/MapInitializer.java index 730e5a4f4c..044fb00947 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/MapInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/MapInitializer.java @@ -20,8 +20,8 @@ import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Fetch; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Initializer; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; @@ -35,45 +35,16 @@ import org.checkerframework.checker.nullness.qual.Nullable; * * @author Steve Ebersole */ -public class MapInitializer extends AbstractImmediateCollectionInitializer { +public class MapInitializer extends AbstractImmediateCollectionInitializer { private static final String CONCRETE_NAME = MapInitializer.class.getSimpleName(); private final DomainResultAssembler mapKeyAssembler; private final DomainResultAssembler mapValueAssembler; - /** - * @deprecated Use {@link #MapInitializer(NavigablePath, PluralAttributeMapping, InitializerParent, LockMode, DomainResult, DomainResult, boolean, AssemblerCreationState, Fetch, Fetch)} instead. - */ - @Deprecated(forRemoval = true) public MapInitializer( NavigablePath navigablePath, PluralAttributeMapping attributeMapping, - FetchParentAccess parentAccess, - LockMode lockMode, - DomainResult collectionKeyResult, - DomainResult collectionValueKeyResult, - Fetch mapKeyFetch, - Fetch mapValueFetch, - boolean isResultInitializer, - AssemblerCreationState creationState) { - this( - navigablePath, - attributeMapping, - (InitializerParent) parentAccess, - lockMode, - collectionKeyResult, - collectionValueKeyResult, - isResultInitializer, - creationState, - mapKeyFetch, - mapValueFetch - ); - } - - public MapInitializer( - NavigablePath navigablePath, - PluralAttributeMapping attributeMapping, - InitializerParent parent, + InitializerParent parent, LockMode lockMode, DomainResult collectionKeyResult, DomainResult collectionValueKeyResult, @@ -91,8 +62,8 @@ public class MapInitializer extends AbstractImmediateCollectionInitializer { isResultInitializer, creationState ); - this.mapKeyAssembler = mapKeyFetch.createAssembler( (InitializerParent) this, creationState ); - this.mapValueAssembler = mapValueFetch.createAssembler( (InitializerParent) this, creationState ); + this.mapKeyAssembler = mapKeyFetch.createAssembler( this, creationState ); + this.mapValueAssembler = mapValueFetch.createAssembler( this, creationState ); } @Override @@ -101,21 +72,21 @@ public class MapInitializer extends AbstractImmediateCollectionInitializer { } @Override - protected void forEachSubInitializer(BiConsumer consumer, X arg) { - super.forEachSubInitializer( consumer, arg ); - final Initializer keyInitializer = mapKeyAssembler.getInitializer(); + protected void forEachSubInitializer(BiConsumer, RowProcessingState> consumer, InitializerData data) { + super.forEachSubInitializer( consumer, data ); + final Initializer keyInitializer = mapKeyAssembler.getInitializer(); if ( keyInitializer != null ) { - consumer.accept( keyInitializer, arg ); + consumer.accept( keyInitializer, data.getRowProcessingState() ); } - final Initializer valueInitializer = mapValueAssembler.getInitializer(); + final Initializer valueInitializer = mapValueAssembler.getInitializer(); if ( valueInitializer != null ) { - consumer.accept( valueInitializer, arg ); + consumer.accept( valueInitializer, data.getRowProcessingState() ); } } @Override - public @Nullable PersistentMap getCollectionInstance() { - return (PersistentMap) super.getCollectionInstance(); + public @Nullable PersistentMap getCollectionInstance(ImmediateCollectionInitializerData data) { + return (PersistentMap) super.getCollectionInstance( data ); } @Override @@ -137,36 +108,38 @@ public class MapInitializer extends AbstractImmediateCollectionInitializer { } @Override - protected void initializeSubInstancesFromParent(RowProcessingState rowProcessingState) { - final Initializer keyInitializer = mapKeyAssembler.getInitializer(); - final Initializer valueInitializer = mapValueAssembler.getInitializer(); + protected void initializeSubInstancesFromParent(ImmediateCollectionInitializerData data) { + final Initializer keyInitializer = mapKeyAssembler.getInitializer(); + final Initializer valueInitializer = mapValueAssembler.getInitializer(); if ( keyInitializer != null || valueInitializer != null ) { - final PersistentMap map = getCollectionInstance(); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final PersistentMap map = getCollectionInstance( data ); assert map != null; for ( Map.Entry entry : map.entrySet() ) { if ( keyInitializer != null ) { - keyInitializer.initializeInstanceFromParent( entry.getKey() ); + keyInitializer.initializeInstanceFromParent( entry.getKey(), rowProcessingState ); } if ( valueInitializer != null ) { - valueInitializer.initializeInstanceFromParent( entry.getValue() ); + valueInitializer.initializeInstanceFromParent( entry.getValue(), rowProcessingState ); } } } } @Override - protected void resolveInstanceSubInitializers(RowProcessingState rowProcessingState) { - final Initializer keyInitializer = mapKeyAssembler.getInitializer(); - final Initializer valueInitializer = mapValueAssembler.getInitializer(); + protected void resolveInstanceSubInitializers(ImmediateCollectionInitializerData data) { + final Initializer keyInitializer = mapKeyAssembler.getInitializer(); + final Initializer valueInitializer = mapValueAssembler.getInitializer(); if ( keyInitializer != null || valueInitializer != null ) { - final PersistentMap map = getCollectionInstance(); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final PersistentMap map = getCollectionInstance( data ); assert map != null; for ( Map.Entry entry : map.entrySet() ) { if ( keyInitializer != null ) { - keyInitializer.resolveInstance( entry.getKey() ); + keyInitializer.resolveInstance( entry.getKey(), rowProcessingState ); } if ( valueInitializer != null ) { - valueInitializer.resolveInstance( entry.getValue() ); + valueInitializer.resolveInstance( entry.getValue(), rowProcessingState ); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/MapInitializerProducer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/MapInitializerProducer.java index 3e12bd5081..6f0bcbdfb2 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/MapInitializerProducer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/MapInitializerProducer.java @@ -12,9 +12,7 @@ import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; -import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Fetch; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.collection.CollectionInitializer; @@ -36,22 +34,10 @@ public class MapInitializerProducer implements CollectionInitializerProducer { } @Override - public CollectionInitializer produceInitializer( - NavigablePath navigablePath, - PluralAttributeMapping attributeMapping, - FetchParentAccess parentAccess, - LockMode lockMode, - DomainResultAssembler collectionKeyAssembler, - DomainResultAssembler collectionValueKeyAssembler, - AssemblerCreationState creationState) { - throw new UnsupportedOperationException( "Use the non-deprecated method variant instead." ); - } - - @Override - public CollectionInitializer produceInitializer( + public CollectionInitializer produceInitializer( NavigablePath navigablePath, PluralAttributeMapping attribute, - InitializerParent parent, + InitializerParent parent, LockMode lockMode, DomainResult collectionKeyResult, DomainResult collectionValueKeyResult, diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/SelectEagerCollectionFetch.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/SelectEagerCollectionFetch.java index 5c00d27a95..d5e2e413b9 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/SelectEagerCollectionFetch.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/SelectEagerCollectionFetch.java @@ -45,7 +45,7 @@ public class SelectEagerCollectionFetch extends CollectionFetch { return false; } - public CollectionInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { + public CollectionInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { return new SelectEagerCollectionInitializer( getNavigablePath(), getFetchedMapping(), diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/SelectEagerCollectionInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/SelectEagerCollectionInitializer.java index c3c81ae276..96f6666b84 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/SelectEagerCollectionInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/SelectEagerCollectionInitializer.java @@ -13,7 +13,6 @@ import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.InitializerParent; import org.checkerframework.checker.nullness.qual.Nullable; @@ -21,54 +20,41 @@ import org.checkerframework.checker.nullness.qual.Nullable; /** * @author Andrea Boriero */ -public class SelectEagerCollectionInitializer extends AbstractCollectionInitializer { - - /** - * @deprecated Use {@link #SelectEagerCollectionInitializer(NavigablePath, PluralAttributeMapping, InitializerParent, DomainResult, AssemblerCreationState)} instead. - */ - @Deprecated(forRemoval = true) - public SelectEagerCollectionInitializer( - NavigablePath fetchedPath, - PluralAttributeMapping fetchedMapping, - FetchParentAccess parentAccess, - @Nullable DomainResult collectionKeyResult, - AssemblerCreationState creationState) { - super( fetchedPath, fetchedMapping, parentAccess, collectionKeyResult, false, creationState ); - } +public class SelectEagerCollectionInitializer extends AbstractCollectionInitializer { public SelectEagerCollectionInitializer( NavigablePath fetchedPath, PluralAttributeMapping fetchedMapping, - InitializerParent parent, + InitializerParent parent, @Nullable DomainResult collectionKeyResult, AssemblerCreationState creationState) { super( fetchedPath, fetchedMapping, parent, collectionKeyResult, false, creationState ); } @Override - public void resolveInstance() { - resolveInstance( rowProcessingState, true ); + public void resolveInstance(CollectionInitializerData data) { + resolveInstance( data, true ); } @Override - public void resolveInstance(@Nullable Object instance) { - resolveInstance( instance, rowProcessingState, true ); + public void resolveInstance(@Nullable Object instance, CollectionInitializerData data) { + resolveInstance( instance, data, true ); } @Override - public void initializeInstanceFromParent(Object parentInstance) { + public void initializeInstanceFromParent(Object parentInstance, CollectionInitializerData data) { final Object instance = getInitializedPart().getValue( parentInstance ); if ( collectionAttributeMapping.getCollectionDescriptor() .getCollectionSemantics() .getCollectionClassification() == CollectionClassification.ARRAY ) { - collectionInstance = rowProcessingState.getSession().getPersistenceContextInternal() - .getCollectionHolder( instance ); + data.setCollectionInstance( data.getRowProcessingState().getSession().getPersistenceContextInternal() + .getCollectionHolder( instance ) ); } else { - collectionInstance = (PersistentCollection) instance; + data.setCollectionInstance( (PersistentCollection) instance ); } - state = State.INITIALIZED; - collectionInstance.forceInitialization(); + data.setState( State.INITIALIZED ); + data.getCollectionInstance().forceInitialization(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/SetInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/SetInitializer.java index e3168ab2e2..51f72e72fe 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/SetInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/SetInitializer.java @@ -19,8 +19,8 @@ import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Fetch; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Initializer; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; @@ -29,42 +29,15 @@ import org.checkerframework.checker.nullness.qual.Nullable; /** * @author Steve Ebersole */ -public class SetInitializer extends AbstractImmediateCollectionInitializer { +public class SetInitializer extends AbstractImmediateCollectionInitializer { private static final String CONCRETE_NAME = SetInitializer.class.getSimpleName(); private final DomainResultAssembler elementAssembler; - /** - * @deprecated Use {@link #SetInitializer(NavigablePath, PluralAttributeMapping, InitializerParent, LockMode, DomainResult, DomainResult, boolean, AssemblerCreationState, Fetch)} instead. - */ - @Deprecated(forRemoval = true) public SetInitializer( NavigablePath navigablePath, PluralAttributeMapping setDescriptor, - FetchParentAccess parentAccess, - LockMode lockMode, - DomainResult collectionKeyResult, - DomainResult collectionValueKeyResult, - Fetch elementFetch, - boolean isResultInitializer, - AssemblerCreationState creationState) { - this( - navigablePath, - setDescriptor, - (InitializerParent) parentAccess, - lockMode, - collectionKeyResult, - collectionValueKeyResult, - isResultInitializer, - creationState, - elementFetch - ); - } - - public SetInitializer( - NavigablePath navigablePath, - PluralAttributeMapping setDescriptor, - InitializerParent parent, + InitializerParent parent, LockMode lockMode, DomainResult collectionKeyResult, DomainResult collectionValueKeyResult, @@ -81,7 +54,7 @@ public class SetInitializer extends AbstractImmediateCollectionInitializer { isResultInitializer, creationState ); - this.elementAssembler = elementFetch.createAssembler( (InitializerParent) this, creationState ); + this.elementAssembler = elementFetch.createAssembler( this, creationState ); } @Override @@ -90,17 +63,17 @@ public class SetInitializer extends AbstractImmediateCollectionInitializer { } @Override - protected void forEachSubInitializer(BiConsumer consumer, X arg) { - super.forEachSubInitializer( consumer, arg ); - final Initializer initializer = elementAssembler.getInitializer(); + protected void forEachSubInitializer(BiConsumer, RowProcessingState> consumer, InitializerData data) { + super.forEachSubInitializer( consumer, data ); + final Initializer initializer = elementAssembler.getInitializer(); if ( initializer != null ) { - consumer.accept( initializer, arg ); + consumer.accept( initializer, data.getRowProcessingState() ); } } @Override - public @Nullable PersistentSet getCollectionInstance() { - return (PersistentSet) super.getCollectionInstance(); + public @Nullable PersistentSet getCollectionInstance(ImmediateCollectionInitializerData data) { + return (PersistentSet) super.getCollectionInstance( data ); } @Override @@ -117,25 +90,27 @@ public class SetInitializer extends AbstractImmediateCollectionInitializer { } @Override - protected void initializeSubInstancesFromParent(RowProcessingState rowProcessingState) { - final Initializer initializer = elementAssembler.getInitializer(); + protected void initializeSubInstancesFromParent(ImmediateCollectionInitializerData data) { + final Initializer initializer = elementAssembler.getInitializer(); if ( initializer != null ) { - final PersistentSet set = getCollectionInstance(); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final PersistentSet set = getCollectionInstance( data ); assert set != null; for ( Object element : set ) { - initializer.initializeInstanceFromParent( element ); + initializer.initializeInstanceFromParent( element, rowProcessingState ); } } } @Override - protected void resolveInstanceSubInitializers(RowProcessingState rowProcessingState) { - final Initializer initializer = elementAssembler.getInitializer(); + protected void resolveInstanceSubInitializers(ImmediateCollectionInitializerData data) { + final Initializer initializer = elementAssembler.getInitializer(); if ( initializer != null ) { - final PersistentSet set = getCollectionInstance(); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final PersistentSet set = getCollectionInstance( data ); assert set != null; for ( Object element : set ) { - initializer.resolveInstance( element ); + initializer.resolveInstance( element, rowProcessingState ); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/SetInitializerProducer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/SetInitializerProducer.java index 3d2ee3cfb3..121e44092f 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/SetInitializerProducer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/SetInitializerProducer.java @@ -12,9 +12,7 @@ import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; -import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Fetch; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.collection.CollectionInitializer; @@ -33,22 +31,10 @@ public class SetInitializerProducer implements CollectionInitializerProducer { } @Override - public CollectionInitializer produceInitializer( - NavigablePath navigablePath, - PluralAttributeMapping attributeMapping, - FetchParentAccess parentAccess, - LockMode lockMode, - DomainResultAssembler collectionKeyAssembler, - DomainResultAssembler collectionValueKeyAssembler, - AssemblerCreationState creationState) { - throw new UnsupportedOperationException( "Use the non-deprecated method variant instead." ); - } - - @Override - public CollectionInitializer produceInitializer( + public CollectionInitializer produceInitializer( NavigablePath navigablePath, PluralAttributeMapping attribute, - InitializerParent parent, + InitializerParent parent, LockMode lockMode, DomainResult collectionKeyResult, DomainResult collectionValueKeyResult, diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/UnfetchedCollectionAssembler.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/UnfetchedCollectionAssembler.java index 8e930887d0..9be2236b6f 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/UnfetchedCollectionAssembler.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/collection/internal/UnfetchedCollectionAssembler.java @@ -9,7 +9,6 @@ package org.hibernate.sql.results.graph.collection.internal; import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer; import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.descriptor.java.JavaType; @@ -22,7 +21,7 @@ public class UnfetchedCollectionAssembler implements DomainResultAssembler { } @Override - public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) { + public Object assemble(RowProcessingState rowProcessingState) { return LazyPropertyInitializer.UNFETCHED_PROPERTY; } @@ -30,4 +29,5 @@ public class UnfetchedCollectionAssembler implements DomainResultAssembler { public JavaType getAssembledJavaType() { return fetchedMapping.getJavaType(); } + } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/EmbeddableInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/EmbeddableInitializer.java index f54b57d192..5a99b9a7ab 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/EmbeddableInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/EmbeddableInitializer.java @@ -8,7 +8,7 @@ package org.hibernate.sql.results.graph.embeddable; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; -import org.hibernate.sql.results.graph.FetchParentAccess; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; @@ -19,40 +19,28 @@ import org.checkerframework.checker.nullness.qual.Nullable; * * @author Steve Ebersole */ -public interface EmbeddableInitializer extends FetchParentAccess { +public interface EmbeddableInitializer extends InitializerParent { @Override EmbeddableValuedModelPart getInitializedPart(); - Object getCompositeInstance(); - - /** - * @deprecated Use {@link #getParent()} instead - */ - @Override - @Deprecated(forRemoval = true) - @Nullable FetchParentAccess getFetchParentAccess(); - - @Override - @Nullable InitializerParent getParent(); - - @Override - default Object getInitializedInstance() { - return getCompositeInstance(); + Object getCompositeInstance(Data data); + default Object getCompositeInstance(RowProcessingState rowProcessingState) { + return getCompositeInstance( getData( rowProcessingState ) ); } + @Override + @Nullable InitializerParent getParent(); + @Override default boolean isEmbeddableInitializer() { return true; } @Override - default EmbeddableInitializer asEmbeddableInitializer() { + default EmbeddableInitializer asEmbeddableInitializer() { return this; } void resolveState(RowProcessingState rowProcessingState); - default Object getDiscriminatorValue() { - return null; - } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/AggregateEmbeddableFetchImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/AggregateEmbeddableFetchImpl.java index 37996ddc42..246e9160be 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/AggregateEmbeddableFetchImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/AggregateEmbeddableFetchImpl.java @@ -26,7 +26,6 @@ import org.hibernate.sql.results.graph.DomainResultAssembler; 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.FetchParentAccess; import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.InitializerProducer; @@ -159,28 +158,21 @@ public class AggregateEmbeddableFetchImpl extends AbstractFetchParent @Override public DomainResultAssembler createAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createAssembler( (InitializerParent) parentAccess, creationState ); - } - - @Override - public DomainResultAssembler createAssembler( - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return new EmbeddableAssembler( creationState.resolveInitializer( this, parent, this ).asEmbeddableInitializer() ); } @Override - public EmbeddableInitializer createInitializer( + public EmbeddableInitializer createInitializer( AggregateEmbeddableFetchImpl resultGraphNode, - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return resultGraphNode.createInitializer( parent, creationState ); } @Override - public EmbeddableInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { + public EmbeddableInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { return new AggregateEmbeddableInitializerImpl( this, discriminatorFetch, diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/AggregateEmbeddableInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/AggregateEmbeddableInitializer.java deleted file mode 100644 index 764cde9cd8..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/AggregateEmbeddableInitializer.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later - * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html - */ -package org.hibernate.sql.results.graph.embeddable.internal; - - -import org.hibernate.sql.ast.spi.SqlSelection; -import org.hibernate.sql.results.graph.FetchParentAccess; -import org.hibernate.sql.results.graph.InitializerParent; -import org.hibernate.sql.results.graph.embeddable.EmbeddableInitializer; -import org.hibernate.sql.results.jdbc.spi.RowProcessingState; - -public interface AggregateEmbeddableInitializer extends EmbeddableInitializer { - - int[] getAggregateValuesArrayPositions(); - - default Object[] getJdbcValues(RowProcessingState processingState) { - final int[] aggregateValuesArrayPositions = getAggregateValuesArrayPositions(); - Object[] jdbcValue = (Object[]) processingState.getJdbcValue( aggregateValuesArrayPositions[0] ); - for ( int i = 1; i < aggregateValuesArrayPositions.length; i++ ) { - if ( jdbcValue == null ) { - break; - } - jdbcValue = (Object[]) jdbcValue[aggregateValuesArrayPositions[i]]; - } - return jdbcValue; - } - - static int[] determineAggregateValuesArrayPositions( - InitializerParent parent, - SqlSelection structSelection) { - if ( parent instanceof AggregateEmbeddableInitializer ) { - final int[] parentAggregateValuesArrayPositions = ( (AggregateEmbeddableInitializer) parent ).getAggregateValuesArrayPositions(); - final int[] aggregateValuesArrayPositions = new int[parentAggregateValuesArrayPositions.length + 1]; - System.arraycopy( - parentAggregateValuesArrayPositions, - 0, - aggregateValuesArrayPositions, - 0, - parentAggregateValuesArrayPositions.length - ); - aggregateValuesArrayPositions[aggregateValuesArrayPositions.length - 1] = structSelection.getValuesArrayPosition(); - return aggregateValuesArrayPositions; - } - else if ( parent instanceof EmbeddableInitializer ) { - return determineAggregateValuesArrayPositions( parent.getParent(), structSelection ); - } - return new int[] { structSelection.getValuesArrayPosition() }; - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/AggregateEmbeddableInitializerImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/AggregateEmbeddableInitializerImpl.java index 3096aa8ac6..48540803dd 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/AggregateEmbeddableInitializerImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/AggregateEmbeddableInitializerImpl.java @@ -13,6 +13,7 @@ import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.basic.BasicFetch; +import org.hibernate.sql.results.graph.embeddable.EmbeddableInitializer; import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; @@ -21,19 +22,19 @@ import org.hibernate.sql.results.jdbc.spi.RowProcessingState; * The aggregate selection reads an Object[] from JDBC which serves as data for the nested {@link DomainResultAssembler}. * This class exposes the Object[] of the aggregate to the nested assemblers through a wrapping {@link RowProcessingState}. */ -public class AggregateEmbeddableInitializerImpl extends EmbeddableInitializerImpl implements AggregateEmbeddableInitializer { +public class AggregateEmbeddableInitializerImpl extends EmbeddableInitializerImpl { private final int[] aggregateValuesArrayPositions; public AggregateEmbeddableInitializerImpl( EmbeddableResultGraphNode resultDescriptor, BasicFetch discriminatorFetch, - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState, boolean isResultInitializer, SqlSelection structSelection) { super( resultDescriptor, discriminatorFetch, parent, creationState, isResultInitializer ); - this.aggregateValuesArrayPositions = AggregateEmbeddableInitializer.determineAggregateValuesArrayPositions( + this.aggregateValuesArrayPositions = determineAggregateValuesArrayPositions( parent, structSelection ); @@ -43,7 +44,7 @@ public class AggregateEmbeddableInitializerImpl extends EmbeddableInitializerImp resultDescriptor.getReferencedMappingType() ); System.arraycopy( assemblers, 0, this.assemblers, 0, assemblers.length ); - final Initializer[][] initializers = createInitializers( assemblers ); + final Initializer[][] initializers = createInitializers( assemblers ); System.arraycopy( initializers, 0, this.subInitializers, 0, initializers.length ); } @@ -62,9 +63,42 @@ public class AggregateEmbeddableInitializerImpl extends EmbeddableInitializerImp return new DomainResultAssembler[embeddableTypeDescriptor.isPolymorphic() ? embeddableTypeDescriptor.getConcreteEmbeddableTypes().size() : 1][]; } - @Override public int[] getAggregateValuesArrayPositions() { return aggregateValuesArrayPositions; } + public Object[] getJdbcValues(RowProcessingState processingState) { + final int[] aggregateValuesArrayPositions = getAggregateValuesArrayPositions(); + Object[] jdbcValue = (Object[]) processingState.getJdbcValue( aggregateValuesArrayPositions[0] ); + for ( int i = 1; i < aggregateValuesArrayPositions.length; i++ ) { + if ( jdbcValue == null ) { + break; + } + jdbcValue = (Object[]) jdbcValue[aggregateValuesArrayPositions[i]]; + } + return jdbcValue; + } + + static int[] determineAggregateValuesArrayPositions( + InitializerParent parent, + SqlSelection structSelection) { + if ( parent instanceof AggregateEmbeddableInitializerImpl ) { + final int[] parentAggregateValuesArrayPositions = ( (AggregateEmbeddableInitializerImpl) parent ).getAggregateValuesArrayPositions(); + final int[] aggregateValuesArrayPositions = new int[parentAggregateValuesArrayPositions.length + 1]; + System.arraycopy( + parentAggregateValuesArrayPositions, + 0, + aggregateValuesArrayPositions, + 0, + parentAggregateValuesArrayPositions.length + ); + aggregateValuesArrayPositions[aggregateValuesArrayPositions.length - 1] = structSelection.getValuesArrayPosition(); + return aggregateValuesArrayPositions; + } + else if ( parent instanceof EmbeddableInitializer ) { + return determineAggregateValuesArrayPositions( parent.getParent(), structSelection ); + } + return new int[] { structSelection.getValuesArrayPosition() }; + } + } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/AggregateEmbeddableResultImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/AggregateEmbeddableResultImpl.java index 29275c0280..5a44ff4ffb 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/AggregateEmbeddableResultImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/AggregateEmbeddableResultImpl.java @@ -27,7 +27,6 @@ import org.hibernate.sql.results.graph.DomainResultAssembler; 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.FetchParentAccess; import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.InitializerProducer; @@ -154,29 +153,22 @@ public class AggregateEmbeddableResultImpl extends AbstractFetchParent implem @Override public DomainResultAssembler createResultAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createResultAssembler( (InitializerParent) parentAccess, creationState ); - } - - @Override - public DomainResultAssembler createResultAssembler( - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { //noinspection unchecked return new EmbeddableAssembler( creationState.resolveInitializer( this, parent, this ).asEmbeddableInitializer() ); } @Override - public Initializer createInitializer( + public Initializer createInitializer( AggregateEmbeddableResultImpl resultGraphNode, - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return resultGraphNode.createInitializer( parent, creationState ); } @Override - public Initializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { + public Initializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { return new AggregateEmbeddableInitializerImpl( this, discriminatorFetch, diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableAssembler.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableAssembler.java index e96a8be641..6ba4a19cd1 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableAssembler.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableAssembler.java @@ -8,9 +8,9 @@ package org.hibernate.sql.results.graph.embeddable.internal; import java.util.function.BiConsumer; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.embeddable.EmbeddableInitializer; import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.descriptor.java.JavaType; @@ -18,10 +18,10 @@ import org.hibernate.type.descriptor.java.JavaType; * @author Steve Ebersole */ public class EmbeddableAssembler implements DomainResultAssembler { - protected final EmbeddableInitializer initializer; + protected final EmbeddableInitializer initializer; - public EmbeddableAssembler(EmbeddableInitializer initializer) { - this.initializer = initializer; + public EmbeddableAssembler(EmbeddableInitializer initializer) { + this.initializer = (EmbeddableInitializer) initializer; } @Override @@ -30,9 +30,10 @@ public class EmbeddableAssembler implements DomainResultAssembler { } @Override - public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) { - initializer.resolveInstance(); - return initializer.getCompositeInstance(); + public Object assemble(RowProcessingState rowProcessingState) { + final InitializerData data = initializer.getData( rowProcessingState ); + initializer.resolveInstance( data ); + return initializer.getCompositeInstance( data ); } @Override @@ -43,7 +44,7 @@ public class EmbeddableAssembler implements DomainResultAssembler { } @Override - public EmbeddableInitializer getInitializer() { + public EmbeddableInitializer getInitializer() { return initializer; } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableExpressionResultImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableExpressionResultImpl.java index d7f10cb6c3..41e19ecd85 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableExpressionResultImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableExpressionResultImpl.java @@ -21,7 +21,6 @@ import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.Fetch; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.InitializerProducer; @@ -126,29 +125,22 @@ public class EmbeddableExpressionResultImpl extends AbstractFetchParent imple @Override public DomainResultAssembler createResultAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createResultAssembler( (InitializerParent) parentAccess, creationState ); - } - - @Override - public DomainResultAssembler createResultAssembler( - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { //noinspection unchecked return new EmbeddableAssembler( creationState.resolveInitializer( this, parent, this ).asEmbeddableInitializer() ); } @Override - public Initializer createInitializer( + public Initializer createInitializer( EmbeddableExpressionResultImpl resultGraphNode, - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return resultGraphNode.createInitializer( parent, creationState ); } @Override - public Initializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { + public Initializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { return new EmbeddableInitializerImpl( this, null, parent, creationState, true ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java index 5958e2d87d..cd18b2f754 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java @@ -8,7 +8,6 @@ package org.hibernate.sql.results.graph.embeddable.internal; import org.hibernate.engine.FetchTiming; import org.hibernate.graph.spi.GraphImplementor; -import org.hibernate.metamodel.mapping.DiscriminatorMapping; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.model.domain.JpaMetamodel; @@ -23,7 +22,6 @@ import org.hibernate.sql.results.graph.DomainResultAssembler; 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.FetchParentAccess; import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.InitializerParent; @@ -150,30 +148,23 @@ public class EmbeddableFetchImpl extends AbstractFetchParent return getFetchContainer(); } - @Override - public DomainResultAssembler createAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createAssembler( (InitializerParent) parentAccess, creationState ); - } - @Override public DomainResultAssembler createAssembler( - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return new EmbeddableAssembler( creationState.resolveInitializer( this, parent, this ).asEmbeddableInitializer() ); } @Override - public Initializer createInitializer( + public Initializer createInitializer( EmbeddableFetchImpl resultGraphNode, - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return resultGraphNode.createInitializer( parent, creationState ); } @Override - public EmbeddableInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { + public EmbeddableInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { return new EmbeddableInitializerImpl( this, discriminatorFetch, parent, creationState, true ); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableForeignKeyResultImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableForeignKeyResultImpl.java index e1a46a5c58..cedb3671a7 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableForeignKeyResultImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableForeignKeyResultImpl.java @@ -20,7 +20,6 @@ import org.hibernate.sql.results.graph.DomainResultAssembler; 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.FetchParentAccess; import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.InitializerParent; @@ -99,29 +98,22 @@ public class EmbeddableForeignKeyResultImpl @Override public DomainResultAssembler createResultAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createResultAssembler( (InitializerParent) parentAccess, creationState ); - } - - @Override - public DomainResultAssembler createResultAssembler( - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { //noinspection unchecked return new EmbeddableAssembler( creationState.resolveInitializer( this, parent, this ).asEmbeddableInitializer() ); } @Override - public Initializer createInitializer( + public Initializer createInitializer( EmbeddableForeignKeyResultImpl resultGraphNode, - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return resultGraphNode.createInitializer( parent, creationState ); } @Override - public EmbeddableInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { + public EmbeddableInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { return getReferencedModePart() instanceof NonAggregatedIdentifierMapping ? new NonAggregatedIdentifierMappingInitializer( this, null, creationState, true ) : new EmbeddableInitializerImpl( this, null, null, creationState, true ); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableInitializerImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableInitializerImpl.java index f50d3a62c6..43932c9982 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableInitializerImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableInitializerImpl.java @@ -13,7 +13,6 @@ import java.util.function.BiConsumer; import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.metamodel.mapping.AttributeMapping; -import org.hibernate.metamodel.mapping.EmbeddableDiscriminatorMapping; import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.VirtualModelPart; @@ -27,15 +26,14 @@ import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Fetch; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.graph.Initializer; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.basic.BasicFetch; import org.hibernate.sql.results.graph.basic.BasicResultAssembler; import org.hibernate.sql.results.graph.collection.CollectionInitializer; import org.hibernate.sql.results.graph.embeddable.EmbeddableInitializer; -import org.hibernate.sql.results.graph.embeddable.EmbeddableLoadingLogger; import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode; import org.hibernate.sql.results.graph.entity.EntityInitializer; import org.hibernate.sql.results.graph.internal.AbstractInitializer; @@ -49,12 +47,12 @@ import static org.hibernate.sql.results.graph.entity.internal.BatchEntityInsideE /** * @author Steve Ebersole */ -public class EmbeddableInitializerImpl extends AbstractInitializer - implements EmbeddableInitializer, ValueAccess { +public class EmbeddableInitializerImpl extends AbstractInitializer + implements EmbeddableInitializer { private final NavigablePath navigablePath; private final EmbeddableValuedModelPart embedded; - private final InitializerParent parent; + private final InitializerParent parent; private final boolean isResultInitializer; private final boolean isPartOfKey; private final boolean createEmptyCompositesEnabled; @@ -62,27 +60,54 @@ public class EmbeddableInitializerImpl extends AbstractInitializer protected final DomainResultAssembler[][] assemblers; private final BasicResultAssembler discriminatorAssembler; - protected final Initializer[][] subInitializers; + protected final Initializer[][] subInitializers; - // per-row state - private final Object[] rowState; - protected Object compositeInstance; - protected EmbeddableMappingType.ConcreteEmbeddableType concreteEmbeddableType; + public static class EmbeddableInitializerData extends InitializerData implements ValueAccess { + protected final InitializerData parentData; + protected final Object[] rowState; + protected EmbeddableMappingType.ConcreteEmbeddableType concreteEmbeddableType; + + public EmbeddableInitializerData(EmbeddableInitializerImpl initializer, RowProcessingState rowProcessingState) { + super( rowProcessingState ); + this.parentData = initializer.parent == null ? null : initializer.parent.getData( rowProcessingState ); + final EmbeddableMappingType embeddableTypeDescriptor = initializer.embedded.getEmbeddableTypeDescriptor(); + final int size = embeddableTypeDescriptor.getNumberOfFetchables(); + this.rowState = new Object[ size ]; + } + + @Override + public Object[] getValues() { + return getState() == State.MISSING ? null : rowState; + } + + @Override + public T getValue(int i, Class clazz) { + return getState() == State.MISSING ? null : clazz.cast( rowState[i] ); + } + + @Override + public Object getOwner() { + return parentData == null ? null : parentData.getInstance(); + } + + public int getSubclassId() { + return concreteEmbeddableType == null ? 0 : concreteEmbeddableType.getSubclassId(); + } + } public EmbeddableInitializerImpl( EmbeddableResultGraphNode resultDescriptor, BasicFetch discriminatorFetch, - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState, boolean isResultInitializer) { + super( creationState ); this.navigablePath = resultDescriptor.getNavigablePath(); this.embedded = resultDescriptor.getReferencedMappingContainer(); - this.parent = parent; + this.parent = (InitializerParent) parent; this.isResultInitializer = isResultInitializer; final EmbeddableMappingType embeddableTypeDescriptor = embedded.getEmbeddableTypeDescriptor(); - final int size = embeddableTypeDescriptor.getNumberOfFetchables(); - this.rowState = new Object[ size ]; this.isPartOfKey = embedded.isEntityIdentifierMapping() || Initializer.isPartOfKey( navigablePath, parent ); // We never want to create empty composites for the FK target or PK, otherwise collections would break @@ -111,7 +136,7 @@ public class EmbeddableInitializerImpl extends AbstractInitializer final DomainResultAssembler stateAssembler = fetch == null ? new NullValueAssembler<>( stateArrayContributor.getJavaType() ) - : fetch.createAssembler( (InitializerParent) this, creationState ); + : fetch.createAssembler( this, creationState ); overallAssemblers[i] = stateAssembler; } @@ -132,15 +157,15 @@ public class EmbeddableInitializerImpl extends AbstractInitializer return new DomainResultAssembler[][] { overallAssemblers }; } - protected static Initializer[][] createInitializers(DomainResultAssembler[][] assemblers) { - Initializer[][] subInitializers = new Initializer[assemblers.length][]; + protected static Initializer[][] createInitializers(DomainResultAssembler[][] assemblers) { + Initializer[][] subInitializers = new Initializer[assemblers.length][]; for ( int i = 0; i < assemblers.length; i++ ) { final DomainResultAssembler[] subAssemblers = assemblers[i]; if ( subAssemblers != null ) { - final ArrayList initializers = new ArrayList<>( subAssemblers.length ); + final ArrayList> initializers = new ArrayList<>( subAssemblers.length ); for ( DomainResultAssembler assembler : subAssemblers ) { if ( assembler != null ) { - final Initializer initializer = assembler.getInitializer(); + final Initializer initializer = assembler.getInitializer(); if ( initializer != null ) { initializers.add( initializer ); } @@ -154,7 +179,8 @@ public class EmbeddableInitializerImpl extends AbstractInitializer subInitializers[i] = Initializer.EMPTY_ARRAY; } } - return subInitializers; + //noinspection unchecked + return (Initializer[][]) subInitializers; } @Override @@ -163,12 +189,7 @@ public class EmbeddableInitializerImpl extends AbstractInitializer } @Override - public @Nullable FetchParentAccess getFetchParentAccess() { - return (FetchParentAccess) parent; - } - - @Override - public @Nullable InitializerParent getParent() { + public @Nullable InitializerParent getParent() { return parent; } @@ -183,8 +204,9 @@ public class EmbeddableInitializerImpl extends AbstractInitializer } @Override - public Object getCompositeInstance() { - return state == State.RESOLVED || state == State.INITIALIZED ? compositeInstance : null; + public Object getCompositeInstance(EmbeddableInitializerData data) { + final State state = data.getState(); + return state == State.RESOLVED || state == State.INITIALIZED ? data.getInstance() : null; } @Override @@ -193,82 +215,87 @@ public class EmbeddableInitializerImpl extends AbstractInitializer } @Override - public void resolveKey() { - if ( state != State.UNINITIALIZED ) { + protected InitializerData createInitializerData(RowProcessingState rowProcessingState) { + return new EmbeddableInitializerData( this, rowProcessingState ); + } + + @Override + public void resolveKey(EmbeddableInitializerData data) { + if ( data.getState() != State.UNINITIALIZED ) { return; } // We need to possibly wrap the processing state if the embeddable is within an aggregate - compositeInstance = null; + data.setInstance( null ); if ( discriminatorAssembler != null ) { - final EmbeddableDiscriminatorMapping discriminatorMapping = embedded.getEmbeddableTypeDescriptor() - .getDiscriminatorMapping(); - assert discriminatorMapping != null; + assert embedded.getEmbeddableTypeDescriptor().getDiscriminatorMapping() != null; // todo: add more info into EmbeddableDiscriminatorConverter to extract this details object directly - final Object discriminatorValue = discriminatorAssembler.extractRawValue( rowProcessingState ); - concreteEmbeddableType = discriminatorValue == null + final Object discriminatorValue = discriminatorAssembler.extractRawValue( data.getRowProcessingState() ); + data.concreteEmbeddableType = discriminatorValue == null ? null : embedded.getEmbeddableTypeDescriptor().findSubtypeByDiscriminator( discriminatorValue ); } if ( isPartOfKey ) { - state = State.KEY_RESOLVED; + data.setState( State.KEY_RESOLVED ); if ( subInitializers.length == 0 ) { // Resolve the component early to know if the key is missing or not - resolveInstance(); + resolveInstance( data ); } else { - resolveKeySubInitializers( rowProcessingState ); + resolveKeySubInitializers( data ); } } else { - super.resolveKey(); + super.resolveKey( data ); } } - private void resolveKeySubInitializers(RowProcessingState rowProcessingState) { - for ( Initializer initializer : subInitializers[getSubclassId()] ) { - initializer.resolveKey(); - if ( initializer.getState() == State.MISSING ) { - state = State.MISSING; + private void resolveKeySubInitializers(EmbeddableInitializerData data) { + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + for ( Initializer initializer : subInitializers[data.getSubclassId()] ) { + final InitializerData subData = initializer.getData( rowProcessingState ); + initializer.resolveKey( subData ); + if ( subData.getState() == State.MISSING ) { + data.setState( State.MISSING ); return; } } } @Override - public void resolveInstance() { - if ( state != State.KEY_RESOLVED ) { + public void resolveInstance(EmbeddableInitializerData data) { + if ( data.getState() != State.KEY_RESOLVED ) { return; } - state = State.RESOLVED; - extractRowState(); - prepareCompositeInstance(); + data.setState( State.RESOLVED ); + extractRowState( data ); + prepareCompositeInstance( data ); } @Override - public void resolveInstance(@Nullable Object instance) { + public void resolveInstance(@Nullable Object instance, EmbeddableInitializerData data) { if ( instance == null ) { - state = State.MISSING; - compositeInstance = null; + data.setState( State.MISSING ); + data.setInstance( null ); } else { - state = State.INITIALIZED; - compositeInstance = instance; - for ( Initializer initializer : subInitializers[getSubclassId()] ) { + data.setState( State.INITIALIZED ); + data.setInstance( instance ); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + for ( Initializer initializer : subInitializers[data.getSubclassId()] ) { final Object subInstance = initializer.getInitializedPart() .asAttributeMapping() .getValue( instance ); if ( subInstance == LazyPropertyInitializer.UNFETCHED_PROPERTY ) { // Go through the normal initializer process - initializer.resolveKey(); + initializer.resolveKey( rowProcessingState ); } else { - initializer.resolveInstance( subInstance ); + initializer.resolveInstance( subInstance, rowProcessingState ); } } - if ( !rowProcessingState.isQueryCacheHit() && rowProcessingState.getQueryOptions().isResultCachingEnabled() == Boolean.TRUE ) { - // Resolve the state of the assemblers if result caching is enabled and this is not a query cache hit - for ( DomainResultAssembler assembler : assemblers[getSubclassId()] ) { + if ( rowProcessingState.needsResolveState() ) { + for ( DomainResultAssembler assembler : assemblers[data.getSubclassId()] ) { assembler.resolveState( rowProcessingState ); } } @@ -276,24 +303,23 @@ public class EmbeddableInitializerImpl extends AbstractInitializer } @Override - public void initializeInstance() { - if ( state != State.RESOLVED ) { + public void initializeInstance(EmbeddableInitializerData data) { + if ( data.getState() != State.RESOLVED ) { return; } - state = State.INITIALIZED; - EmbeddableLoadingLogger.EMBEDDED_LOAD_LOGGER.debugf( "Initializing composite instance [%s]", navigablePath ); + data.setState( State.INITIALIZED ); if ( embedded.getParentInjectionAttributePropertyAccess() != null || embedded instanceof VirtualModelPart ) { - handleParentInjection(); + handleParentInjection( data ); - final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( compositeInstance ); + final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( data.getInstance() ); // If the composite instance has a lazy initializer attached, this means that the embeddable is actually virtual // and the compositeInstance == entity, so we have to inject the row state into the entity when it finishes resolution if ( lazyInitializer != null ) { if ( parent != null ) { embedded.getEmbeddableTypeDescriptor().setValues( lazyInitializer.getImplementation(), - rowState + data.rowState ); } else { @@ -305,88 +331,84 @@ public class EmbeddableInitializerImpl extends AbstractInitializer // interprets that as the values are not known or were all null. final Object target = embedded.getEmbeddableTypeDescriptor().getRepresentationStrategy() .getInstantiator() - .instantiate( this, sessionFactory ); + .instantiate( data, sessionFactory ); lazyInitializer.setImplementation( target ); } } else { - embedded.getEmbeddableTypeDescriptor().setValues( compositeInstance, rowState ); + embedded.getEmbeddableTypeDescriptor().setValues( data.getInstance(), data.rowState ); } } } @Override - protected void forEachSubInitializer(BiConsumer consumer, X arg) { - if ( concreteEmbeddableType == null ) { - for ( Initializer[] initializers : subInitializers ) { - for ( Initializer initializer : initializers ) { - consumer.accept( initializer, arg ); + protected void forEachSubInitializer(BiConsumer, RowProcessingState> consumer, InitializerData data) { + final EmbeddableInitializerData embeddableInitializerData = (EmbeddableInitializerData) data; + final RowProcessingState rowProcessingState = embeddableInitializerData.getRowProcessingState(); + if ( embeddableInitializerData.concreteEmbeddableType == null ) { + for ( Initializer[] initializers : subInitializers ) { + for ( Initializer initializer : initializers ) { + consumer.accept( initializer, rowProcessingState ); } } } else { - for ( Initializer initializer : subInitializers[getSubclassId()] ) { - consumer.accept( initializer, arg ); + for ( Initializer initializer : subInitializers[embeddableInitializerData.getSubclassId()] ) { + consumer.accept( initializer, rowProcessingState ); } } } @Override - public void initializeInstanceFromParent(Object parentInstance) { + public void initializeInstanceFromParent(Object parentInstance, EmbeddableInitializerData data) { final AttributeMapping attributeMapping = getInitializedPart().asAttributeMapping(); final Object instance = attributeMapping != null ? attributeMapping.getValue( parentInstance ) : parentInstance; - compositeInstance = instance; + data.setInstance( instance ); if ( instance == null ) { - state = State.MISSING; + data.setState( State.MISSING ); } else { - state = State.INITIALIZED; - for ( Initializer initializer : subInitializers[getSubclassId()] ) { - initializer.initializeInstanceFromParent( instance ); + data.setState( State.INITIALIZED ); + for ( Initializer initializer : subInitializers[data.getSubclassId()] ) { + initializer.initializeInstanceFromParent( instance, data.getRowProcessingState() ); } } } - private void prepareCompositeInstance() { + private void prepareCompositeInstance(EmbeddableInitializerData data) { // Virtual model parts use the owning entity as container which the fetch parent access provides. // For an identifier or foreign key this is called during the resolveKey phase of the fetch parent, // so we can't use the fetch parent access in that case. if ( parent != null && embedded instanceof VirtualModelPart && !isPartOfKey ) { - parent.resolveInstance(); - compositeInstance = parent.getInitializedInstance(); - EntityInitializer entityInitializer = parent.asEntityInitializer(); - if ( entityInitializer != null && entityInitializer.isEntityInitialized() ) { + final InitializerData subData = parent.getData( data.getRowProcessingState() ); + parent.resolveInstance( subData ); + data.setInstance( parent.getResolvedInstance( subData ) ); + if ( data.getState() == State.INITIALIZED ) { return; } } - if ( compositeInstance == null ) { - compositeInstance = createCompositeInstance(); + if ( data.getInstance() == null ) { + data.setInstance( createCompositeInstance( data ) ); } - - EmbeddableLoadingLogger.EMBEDDED_LOAD_LOGGER.debugf( - "Created composite instance [%s]", - navigablePath - ); } - private void extractRowState() { + private void extractRowState(EmbeddableInitializerData data) { boolean stateAllNull = true; - final DomainResultAssembler[] subAssemblers = assemblers[getSubclassId()]; + final DomainResultAssembler[] subAssemblers = assemblers[data.getSubclassId()]; for ( int i = 0; i < subAssemblers.length; i++ ) { final DomainResultAssembler assembler = subAssemblers[i]; final Object contributorValue = assembler == null ? null : assembler.assemble( - rowProcessingState, - rowProcessingState.getJdbcValuesSourceProcessingState().getProcessingOptions() + data.getRowProcessingState() ); if ( contributorValue == BATCH_PROPERTY ) { - rowState[i] = null; + data.rowState[i] = null; } else { - rowState[i] = contributorValue; + data.rowState[i] = contributorValue; } if ( contributorValue != null ) { stateAllNull = false; @@ -398,19 +420,20 @@ public class EmbeddableInitializerImpl extends AbstractInitializer } } if ( stateAllNull ) { - state = State.MISSING; + data.setState( State.MISSING ); } } @Override public void resolveState(RowProcessingState rowProcessingState) { - for ( final DomainResultAssembler assembler : assemblers[getSubclassId()] ) { + final EmbeddableInitializerData data = getData( rowProcessingState ); + for ( final DomainResultAssembler assembler : assemblers[data.getSubclassId()] ) { assembler.resolveState( rowProcessingState ); } } - private Object createCompositeInstance() { - if ( state == State.MISSING ) { + private Object createCompositeInstance(EmbeddableInitializerData data) { + if ( data.getState() == State.MISSING ) { // todo (6.0) : should we initialize the composite instance if it has a parent attribute? // if ( !createEmptyCompositesEnabled && embedded.getParentInjectionAttributePropertyAccess() == null ) { if ( !createEmptyCompositesEnabled ) { @@ -418,72 +441,38 @@ public class EmbeddableInitializerImpl extends AbstractInitializer } } - final EmbeddableInstantiator instantiator = concreteEmbeddableType == null + final EmbeddableInstantiator instantiator = data.concreteEmbeddableType == null ? embedded.getEmbeddableTypeDescriptor().getRepresentationStrategy().getInstantiator() - : concreteEmbeddableType.getInstantiator(); - final Object instance = instantiator.instantiate( this, sessionFactory ); - state = State.RESOLVED; - - EmbeddableLoadingLogger.EMBEDDED_LOAD_LOGGER.debugf( "Created composite instance [%s] : %s", navigablePath, instance ); - + : data.concreteEmbeddableType.getInstantiator(); + final Object instance = instantiator.instantiate( data, sessionFactory ); + data.setState( State.RESOLVED ); return instance; } - @Override - public Object[] getValues() { - return state == State.MISSING ? null : rowState; - } - - @Override - public T getValue(int i, Class clazz) { - return state == State.MISSING ? null : clazz.cast( rowState[i] ); - } - - public int getSubclassId() { - return concreteEmbeddableType == null ? 0 : concreteEmbeddableType.getSubclassId(); - } - - @Override - public Object getOwner() { - return parent.getInitializedInstance(); - } - - private void handleParentInjection() { + private void handleParentInjection(EmbeddableInitializerData data) { final PropertyAccess parentInjectionAccess = embedded.getParentInjectionAttributePropertyAccess(); if ( parentInjectionAccess == null ) { // embeddable defined no parent injection return; } - final Initializer owningInitializer = determineOwningInitializer(); - final Object parent = determineParentInstance( owningInitializer ); + final Initializer owningInitializer = determineOwningInitializer(); + final Object parent = determineParentInstance( owningInitializer, data.getRowProcessingState() ); if ( parent == null ) { - EmbeddableLoadingLogger.EMBEDDED_LOAD_LOGGER.debugf( - "Unable to determine parent for injection into embeddable [%s]", - navigablePath - ); return; } - EmbeddableLoadingLogger.EMBEDDED_LOAD_LOGGER.debugf( - "Injecting parent into embeddable [%s] : `%s` -> `%s`", - navigablePath, - parent, - compositeInstance - ); - - final Setter setter = parentInjectionAccess.getSetter(); assert setter != null; - setter.set( compositeInstance, parent ); + setter.set( data.getInstance(), parent ); } - private Initializer determineOwningInitializer() { + private Initializer determineOwningInitializer() { // Try to find the first non-embeddable fetch parent access // todo (6.x) - allow injection of containing composite as parent if // it is the direct parent - InitializerParent parent = this.parent; + InitializerParent parent = this.parent; while ( parent != null ) { if ( !parent.isEmbeddableInitializer() ) { return parent; @@ -493,19 +482,19 @@ public class EmbeddableInitializerImpl extends AbstractInitializer throw new UnsupportedOperationException( "Injection of parent instance into embeddable result is not possible" ); } - private Object determineParentInstance(Initializer parentInitializer) { + private Object determineParentInstance(Initializer parentInitializer, RowProcessingState rowProcessingState) { if ( parentInitializer == null ) { throw new UnsupportedOperationException( "Cannot determine Embeddable: " + navigablePath + " parent instance, parent initializer is null" ); } - final CollectionInitializer collectionInitializer = parentInitializer.asCollectionInitializer(); + final CollectionInitializer collectionInitializer = parentInitializer.asCollectionInitializer(); if ( collectionInitializer != null ) { - return collectionInitializer.getCollectionInstance().getOwner(); + return collectionInitializer.getCollectionInstance( rowProcessingState ).getOwner(); } - final EntityInitializer parentEntityInitializer = parentInitializer.asEntityInitializer(); + final EntityInitializer parentEntityInitializer = parentInitializer.asEntityInitializer(); if ( parentEntityInitializer != null ) { - return parentEntityInitializer.getTargetInstance(); + return parentEntityInitializer.getTargetInstance( rowProcessingState ); } throw new UnsupportedOperationException( "The Embeddable: " + navigablePath + " parent initializer is neither an instance of an EntityInitializer nor of a CollectionInitializer" ); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableResultImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableResultImpl.java index bd8b32fdbb..ecc4918b0c 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableResultImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableResultImpl.java @@ -20,7 +20,6 @@ import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.Fetch; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.InitializerProducer; @@ -128,29 +127,22 @@ public class EmbeddableResultImpl extends AbstractFetchParent implements Embe @Override public DomainResultAssembler createResultAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createResultAssembler( (InitializerParent) parentAccess, creationState ); - } - - @Override - public DomainResultAssembler createResultAssembler( - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { //noinspection unchecked return new EmbeddableAssembler( creationState.resolveInitializer( this, parent, this ).asEmbeddableInitializer() ); } @Override - public Initializer createInitializer( + public Initializer createInitializer( EmbeddableResultImpl resultGraphNode, - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return resultGraphNode.createInitializer( parent, creationState ); } @Override - public Initializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { + public Initializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { return new EmbeddableInitializerImpl( this, discriminatorFetch, parent, creationState, true ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/NestedRowProcessingState.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/NestedRowProcessingState.java index 9a0a42a627..d98d65cdcb 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/NestedRowProcessingState.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/NestedRowProcessingState.java @@ -6,6 +6,7 @@ */ package org.hibernate.sql.results.graph.embeddable.internal; +import org.hibernate.LockMode; import org.hibernate.engine.spi.CollectionKey; import org.hibernate.engine.spi.EntityHolder; import org.hibernate.metamodel.mapping.EntityMappingType; @@ -14,17 +15,18 @@ import org.hibernate.query.spi.QueryParameterBindings; import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor; import org.hibernate.sql.exec.internal.BaseExecutionContext; import org.hibernate.sql.exec.spi.Callback; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.entity.EntityFetch; import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingState; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.sql.results.spi.RowReader; public class NestedRowProcessingState extends BaseExecutionContext implements RowProcessingState { - private final AggregateEmbeddableInitializer aggregateEmbeddableInitializer; + private final AggregateEmbeddableInitializerImpl aggregateEmbeddableInitializer; final RowProcessingState processingState; public NestedRowProcessingState( - AggregateEmbeddableInitializer aggregateEmbeddableInitializer, + AggregateEmbeddableInitializerImpl aggregateEmbeddableInitializer, RowProcessingState processingState) { super( processingState.getSession() ); this.aggregateEmbeddableInitializer = aggregateEmbeddableInitializer; @@ -32,7 +34,7 @@ public class NestedRowProcessingState extends BaseExecutionContext implements Ro } public static NestedRowProcessingState wrap( - AggregateEmbeddableInitializer aggregateEmbeddableInitializer, + AggregateEmbeddableInitializerImpl aggregateEmbeddableInitializer, RowProcessingState processingState) { if ( processingState instanceof NestedRowProcessingState ) { return new NestedRowProcessingState( @@ -56,11 +58,31 @@ public class NestedRowProcessingState extends BaseExecutionContext implements Ro // -- delegate the rest + @Override + public T getInitializerData(int initializerId) { + return processingState.getInitializerData( initializerId ); + } + + @Override + public void setInitializerData(int initializerId, InitializerData state) { + processingState.setInitializerData( initializerId, state ); + } + @Override public JdbcValuesSourceProcessingState getJdbcValuesSourceProcessingState() { return processingState.getJdbcValuesSourceProcessingState(); } + @Override + public LockMode determineEffectiveLockMode(String alias) { + return processingState.determineEffectiveLockMode( alias ); + } + + @Override + public boolean needsResolveState() { + return processingState.needsResolveState(); + } + @Override public RowReader getRowReader() { return processingState.getRowReader(); @@ -76,11 +98,6 @@ public class NestedRowProcessingState extends BaseExecutionContext implements Ro return processingState.isQueryCacheHit(); } - @Override - public void finishRowProcessing() { - processingState.finishRowProcessing(); - } - @Override public void finishRowProcessing(boolean wasAdded) { processingState.finishRowProcessing( wasAdded ); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/NonAggregatedIdentifierMappingFetch.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/NonAggregatedIdentifierMappingFetch.java index 7af15a8c53..f1de62f0e0 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/NonAggregatedIdentifierMappingFetch.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/NonAggregatedIdentifierMappingFetch.java @@ -31,7 +31,7 @@ public class NonAggregatedIdentifierMappingFetch extends EmbeddableFetchImpl { } @Override - public EmbeddableInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { + public EmbeddableInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { return new NonAggregatedIdentifierMappingInitializer( this, parent, creationState, false ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/NonAggregatedIdentifierMappingInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/NonAggregatedIdentifierMappingInitializer.java index bcd7014269..843160e595 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/NonAggregatedIdentifierMappingInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/NonAggregatedIdentifierMappingInitializer.java @@ -26,12 +26,11 @@ import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Fetch; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.graph.Initializer; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.embeddable.EmbeddableInitializer; -import org.hibernate.sql.results.graph.embeddable.EmbeddableLoadingLogger; import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode; import org.hibernate.sql.results.graph.internal.AbstractInitializer; import org.hibernate.sql.results.internal.NullValueAssembler; @@ -44,32 +43,59 @@ import static org.hibernate.sql.results.graph.entity.internal.BatchEntityInsideE /** * @author Steve Ebersole */ -public class NonAggregatedIdentifierMappingInitializer extends AbstractInitializer - implements EmbeddableInitializer, ValueAccess { +public class NonAggregatedIdentifierMappingInitializer extends AbstractInitializer + implements EmbeddableInitializer { private final NavigablePath navigablePath; private final NonAggregatedIdentifierMapping embedded; private final EmbeddableMappingType representationEmbeddable; private final EmbeddableRepresentationStrategy representationStrategy; - private final @Nullable InitializerParent parent; + private final @Nullable InitializerParent parent; private final SessionFactoryImplementor sessionFactory; private final boolean isResultInitializer; private final DomainResultAssembler[] assemblers; - private final Initializer[] initializers; + private final Initializer[] initializers; private final boolean hasIdClass; + public static class NonAggregatedIdentifierMappingInitializerData extends InitializerData implements ValueAccess { + protected final InitializerData parentData; + protected final Object[] virtualIdState; + protected final Object[] idClassState; - // per-row state - private final Object[] virtualIdState; - private final Object[] idClassState; - protected Object compositeInstance; + public NonAggregatedIdentifierMappingInitializerData(NonAggregatedIdentifierMappingInitializer initializer, RowProcessingState rowProcessingState) { + super( rowProcessingState ); + this.parentData = initializer.parent == null ? null : initializer.parent.getData( rowProcessingState ); + final EmbeddableMappingType virtualIdEmbeddable = initializer.embedded.getEmbeddableTypeDescriptor(); + final int size = virtualIdEmbeddable.getNumberOfFetchables(); + this.virtualIdState = new Object[ size ]; + this.idClassState = new Object[ size ]; + } + + @Override + public Object[] getValues() { + assert getState() == State.RESOLVED; + return idClassState; + } + + @Override + public T getValue(int i, Class clazz) { + assert getState() == State.RESOLVED; + return clazz.cast( idClassState[i] ); + } + + @Override + public Object getOwner() { + return parentData == null ? null : parentData.getInstance(); + } + } public NonAggregatedIdentifierMappingInitializer( EmbeddableResultGraphNode resultDescriptor, - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState, boolean isResultInitializer) { + super( creationState ); this.navigablePath = resultDescriptor.getNavigablePath(); this.embedded = (NonAggregatedIdentifierMapping) resultDescriptor.getReferencedMappingContainer(); this.parent = parent; @@ -80,25 +106,23 @@ public class NonAggregatedIdentifierMappingInitializer extends AbstractInitializ this.representationStrategy = representationEmbeddable.getRepresentationStrategy(); this.hasIdClass = embedded.hasContainingClass() && virtualIdEmbeddable != representationEmbeddable; - final int size = virtualIdEmbeddable.getNumberOfFetchables(); - this.virtualIdState = new Object[ size ]; - this.idClassState = new Object[ size ]; - this.sessionFactory = creationState.getSqlAstCreationContext().getSessionFactory(); this.assemblers = createAssemblers( this, resultDescriptor, creationState, virtualIdEmbeddable ); - final ArrayList initializers = new ArrayList<>( assemblers.length ); + final ArrayList> initializers = new ArrayList<>( assemblers.length ); for ( DomainResultAssembler assembler : assemblers ) { - final Initializer initializer = assembler.getInitializer(); + final Initializer initializer = assembler.getInitializer(); if ( initializer != null ) { initializers.add( initializer ); } } - this.initializers = initializers.isEmpty() ? Initializer.EMPTY_ARRAY : initializers.toArray( EMPTY_ARRAY ); + //noinspection unchecked + this.initializers = (Initializer[]) ( + initializers.isEmpty() ? Initializer.EMPTY_ARRAY : initializers.toArray( EMPTY_ARRAY ) + ); } - protected static DomainResultAssembler[] createAssemblers( - InitializerParent parent, + InitializerParent parent, EmbeddableResultGraphNode resultDescriptor, AssemblerCreationState creationState, EmbeddableMappingType embeddableTypeDescriptor) { @@ -123,12 +147,7 @@ public class NonAggregatedIdentifierMappingInitializer extends AbstractInitializ } @Override - public @Nullable FetchParentAccess getFetchParentAccess() { - return (FetchParentAccess) parent; - } - - @Override - public @Nullable InitializerParent getParent() { + public @Nullable InitializerParent getParent() { return parent; } @@ -143,27 +162,35 @@ public class NonAggregatedIdentifierMappingInitializer extends AbstractInitializ } @Override - public Object getCompositeInstance() { - return state == State.RESOLVED || state == State.INITIALIZED ? compositeInstance : null; + public Object getCompositeInstance(NonAggregatedIdentifierMappingInitializerData data) { + final State state = data.getState(); + return state == State.RESOLVED || state == State.INITIALIZED ? data.getInstance() : null; } @Override - public void resolveKey() { - if ( state != State.UNINITIALIZED ) { + protected InitializerData createInitializerData(RowProcessingState rowProcessingState) { + return new NonAggregatedIdentifierMappingInitializerData( this, rowProcessingState ); + } + + @Override + public void resolveKey(NonAggregatedIdentifierMappingInitializerData data) { + if ( data.getState() != State.UNINITIALIZED ) { return; } // We need to possibly wrap the processing state if the embeddable is within an aggregate - compositeInstance = null; - state = State.KEY_RESOLVED; + data.setInstance( null ); + data.setState( State.KEY_RESOLVED ); if ( initializers.length == 0 ) { // Resolve the component early to know if the key is missing or not - resolveInstance(); + resolveInstance( data ); } else { - for ( Initializer initializer : initializers ) { - initializer.resolveKey(); - if ( initializer.getState() == State.MISSING ) { - state = State.MISSING; + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + for ( Initializer initializer : initializers ) { + final InitializerData subData = initializer.getData( rowProcessingState ); + initializer.resolveKey( subData ); + if ( subData.getState() == State.MISSING ) { + data.setState( State.MISSING ); return; } } @@ -171,51 +198,51 @@ public class NonAggregatedIdentifierMappingInitializer extends AbstractInitializ } @Override - public void resolveInstance() { - if ( state != State.KEY_RESOLVED ) { + public void resolveInstance(NonAggregatedIdentifierMappingInitializerData data) { + if ( data.getState() != State.KEY_RESOLVED ) { return; } // If we don't have an id class and this is a find by id lookup, we just use that instance - if ( isFindByIdLookup() ) { - compositeInstance = rowProcessingState.getEntityId(); - state = State.INITIALIZED; + if ( isFindByIdLookup( data.getRowProcessingState() ) ) { + data.setInstance( data.getRowProcessingState().getEntityId() ); + data.setState( State.INITIALIZED ); return; } - state = State.RESOLVED; + data.setState( State.RESOLVED ); // We need to possibly wrap the processing state if the embeddable is within an aggregate - extractRowState(); - if ( state == State.MISSING ) { - compositeInstance = null; + extractRowState( data ); + if ( data.getState() == State.MISSING ) { + data.setInstance( null ); } else { - compositeInstance = representationStrategy.getInstantiator().instantiate( this, sessionFactory ); + data.setInstance( representationStrategy.getInstantiator().instantiate( data, sessionFactory ) ); } } @Override - public void resolveInstance(@Nullable Object instance) { + public void resolveInstance(@Nullable Object instance, NonAggregatedIdentifierMappingInitializerData data) { if ( instance == null ) { - state = State.MISSING; - compositeInstance = null; + data.setState( State.MISSING ); + data.setInstance( null ); } else { - state = State.INITIALIZED; - compositeInstance = instance; - for ( Initializer initializer : initializers ) { + data.setState( State.INITIALIZED ); + data.setInstance( instance ); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + for ( Initializer initializer : initializers ) { final Object subInstance = initializer.getInitializedPart() .asAttributeMapping() .getValue( instance ); if ( subInstance == LazyPropertyInitializer.UNFETCHED_PROPERTY ) { // Go through the normal initializer process - initializer.resolveKey(); + initializer.resolveKey( rowProcessingState ); } else { - initializer.resolveInstance( subInstance ); + initializer.resolveInstance( subInstance, rowProcessingState ); } } - if ( !rowProcessingState.isQueryCacheHit() && rowProcessingState.getQueryOptions().isResultCachingEnabled() == Boolean.TRUE ) { - // Resolve the state of the assemblers if result caching is enabled and this is not a query cache hit + if ( rowProcessingState.needsResolveState() ) { for ( DomainResultAssembler assembler : assemblers ) { assembler.resolveState( rowProcessingState ); } @@ -224,16 +251,15 @@ public class NonAggregatedIdentifierMappingInitializer extends AbstractInitializ } @Override - public void initializeInstance() { - if ( state != State.RESOLVED ) { + public void initializeInstance(NonAggregatedIdentifierMappingInitializerData data) { + if ( data.getState() != State.RESOLVED ) { return; } - state = State.INITIALIZED; - EmbeddableLoadingLogger.EMBEDDED_LOAD_LOGGER.debugf( "Initializing composite instance [%s]", navigablePath ); + data.setState( State.INITIALIZED ); if ( parent != null ) { assert parent.isEntityInitializer(); - final Object parentInstance = parent.getInitializedInstance(); + final Object parentInstance = parent.getResolvedInstance( data.getRowProcessingState() ); assert parentInstance != null; final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( parentInstance ); // If the composite instance has a lazy initializer attached, this means that the embeddable is actually virtual @@ -241,48 +267,46 @@ public class NonAggregatedIdentifierMappingInitializer extends AbstractInitializ if ( lazyInitializer != null ) { embedded.getVirtualIdEmbeddable().setValues( lazyInitializer.getImplementation(), - virtualIdState + data.virtualIdState ); } else { - embedded.getVirtualIdEmbeddable().setValues( parentInstance, virtualIdState ); + embedded.getVirtualIdEmbeddable().setValues( parentInstance, data.virtualIdState ); } } } @Override - protected void forEachSubInitializer(BiConsumer consumer, X arg) { - for ( Initializer initializer : initializers ) { - consumer.accept( initializer, arg ); + protected void forEachSubInitializer(BiConsumer, RowProcessingState> consumer, InitializerData data) { + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + for ( Initializer initializer : initializers ) { + consumer.accept( initializer, rowProcessingState ); } } - private boolean isFindByIdLookup() { + private boolean isFindByIdLookup(RowProcessingState rowProcessingState) { return !hasIdClass && rowProcessingState.getEntityId() != null && navigablePath.getParent().getParent() == null && navigablePath instanceof EntityIdentifierNavigablePath; } - private void extractRowState() { + private void extractRowState(NonAggregatedIdentifierMappingInitializerData data) { for ( int i = 0; i < assemblers.length; i++ ) { final DomainResultAssembler assembler = assemblers[i]; - final Object contributorValue = assembler.assemble( - rowProcessingState, - rowProcessingState.getJdbcValuesSourceProcessingState().getProcessingOptions() - ); + final Object contributorValue = assembler.assemble( data.getRowProcessingState() ); if ( contributorValue == null ) { // This is a key and there is a null part, the whole thing has to be turned into null - state = State.MISSING; + data.setState( State.MISSING ); return; } if ( contributorValue == BATCH_PROPERTY ) { - virtualIdState[i] = null; - idClassState[i] = null; + data.virtualIdState[i] = null; + data.idClassState[i] = null; } else { - virtualIdState[i] = contributorValue; - idClassState[i] = contributorValue; + data.virtualIdState[i] = contributorValue; + data.idClassState[i] = contributorValue; if ( hasIdClass ) { final AttributeMapping virtualIdAttribute = embedded.getEmbeddableTypeDescriptor().getAttributeMapping( i ); final AttributeMapping mappedIdAttribute = representationEmbeddable.getAttributeMapping( i ); @@ -291,11 +315,11 @@ public class NonAggregatedIdentifierMappingInitializer extends AbstractInitializ final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) virtualIdAttribute; final ForeignKeyDescriptor fkDescriptor = toOneAttributeMapping.getForeignKeyDescriptor(); final Object associationKey = fkDescriptor.getAssociationKeyFromSide( - virtualIdState[i], + data.virtualIdState[i], toOneAttributeMapping.getSideNature().inverse(), - rowProcessingState.getSession() + data.getRowProcessingState().getSession() ); - idClassState[i] = associationKey; + data.idClassState[i] = associationKey; } } } @@ -304,30 +328,13 @@ public class NonAggregatedIdentifierMappingInitializer extends AbstractInitializ @Override public void resolveState(RowProcessingState rowProcessingState) { - if ( !isFindByIdLookup() ) { + if ( !isFindByIdLookup( rowProcessingState ) ) { for ( final DomainResultAssembler assembler : assemblers ) { assembler.resolveState( rowProcessingState ); } } } - @Override - public Object[] getValues() { - assert state == State.RESOLVED; - return idClassState; - } - - @Override - public T getValue(int i, Class clazz) { - assert state == State.RESOLVED; - return clazz.cast( idClassState[i] ); - } - - @Override - public Object getOwner() { - return parent == null ? null : parent.getInitializedInstance(); - } - @Override public boolean isPartOfKey() { return true; diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/NonAggregatedIdentifierMappingResult.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/NonAggregatedIdentifierMappingResult.java index da8bd0911b..bf6ca0b481 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/NonAggregatedIdentifierMappingResult.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/NonAggregatedIdentifierMappingResult.java @@ -23,9 +23,9 @@ public class NonAggregatedIdentifierMappingResult extends EmbeddableResultImp } @Override - public Initializer createInitializer( + public Initializer createInitializer( EmbeddableResultImpl resultGraphNode, - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return new NonAggregatedIdentifierMappingInitializer( resultGraphNode, parent, creationState, true ); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/EntityInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/EntityInitializer.java index 2315e8055d..eb81a4a4bb 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/EntityInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/EntityInitializer.java @@ -8,7 +8,8 @@ package org.hibernate.sql.results.graph.entity; import org.hibernate.engine.spi.EntityKey; import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.sql.results.graph.FetchParentAccess; +import org.hibernate.sql.results.graph.InitializerData; +import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.checkerframework.checker.nullness.qual.Nullable; @@ -18,64 +19,52 @@ import org.checkerframework.checker.nullness.qual.Nullable; * * @author Steve Ebersole */ -public interface EntityInitializer extends FetchParentAccess { +public interface EntityInitializer extends InitializerParent { /** * Get the descriptor for the type of entity being initialized */ EntityPersister getEntityDescriptor(); - EntityPersister getConcreteDescriptor(); + EntityPersister getConcreteDescriptor(Data data); - @Override - default @Nullable EntityInitializer findFirstEntityDescriptorAccess() { - // Keep this method around for binary backwards compatibility - return this; - } - - @Override - default EntityInitializer findFirstEntityInitializer() { - return this; + default EntityPersister getConcreteDescriptor(RowProcessingState rowProcessingState) { + return getConcreteDescriptor( getData( rowProcessingState ) ); } /** * Get the entity instance for the currently processing "row". * * @apiNote Calling this method is only valid from the time - * {@link #resolveKey} has been called until {@link #finishUpRow} + * {@link #resolveKey(InitializerData)} has been called until {@link #finishUpRow(InitializerData)} * has been called for the currently processing row */ - Object getEntityInstance(); - - default Object getManagedInstance() { - return getEntityInstance(); + Object getEntityInstance(Data data); + default Object getEntityInstance(RowProcessingState rowProcessingState) { + return getEntityInstance( getData( rowProcessingState ) ); } - default Object getTargetInstance() { - return getEntityInstance(); + default Object getTargetInstance(Data data) { + return getEntityInstance( data ); } - - @Override - default Object getInitializedInstance() { - return getEntityInstance(); + default Object getTargetInstance(RowProcessingState rowProcessingState) { + return getTargetInstance( getData( rowProcessingState ) ); } default @Nullable EntityKey resolveEntityKeyOnly(RowProcessingState rowProcessingState) { - resolveKey(); - final EntityKey entityKey = getEntityKey(); - finishUpRow(); + final Data data = getData( rowProcessingState ); + resolveKey( data ); + final EntityKey entityKey = new EntityKey( + getEntityIdentifier( data ), + getConcreteDescriptor( data ) + ); + finishUpRow( data ); return entityKey; } - /** - * @deprecated Use {@link #resolveEntityKeyOnly(RowProcessingState)} instead. - */ - @Deprecated(forRemoval = true) - @Nullable EntityKey getEntityKey(); - - default @Nullable Object getEntityIdentifier() { - final EntityKey entityKey = getEntityKey(); - return entityKey == null ? null : entityKey.getIdentifier(); + @Nullable Object getEntityIdentifier(Data data); + default @Nullable Object getEntityIdentifier(RowProcessingState rowProcessingState) { + return getEntityIdentifier( getData( rowProcessingState ) ); } @Override @@ -84,13 +73,8 @@ public interface EntityInitializer extends FetchParentAccess { } @Override - default EntityInitializer asEntityInitializer() { + default EntityInitializer asEntityInitializer() { return this; } - /** - * @return true if the current entity associated to this EntityInitializer has been initialized - */ - boolean isEntityInitialized(); - } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/LoadingEntityEntry.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/LoadingEntityEntry.java deleted file mode 100644 index b11c3e98eb..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/LoadingEntityEntry.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later - * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html - */ -package org.hibernate.sql.results.graph.entity; - -import java.util.Locale; - -import org.hibernate.engine.spi.EntityKey; -import org.hibernate.persister.entity.EntityPersister; - -/** - * Representation of an entity being loaded, containing its state - * - * @author Steve Ebersole - * @deprecated Now modeled through {@link org.hibernate.engine.spi.EntityHolder} - */ -@Deprecated(forRemoval = true) -public class LoadingEntityEntry { - private final EntityInitializer entityInitializer; - private final EntityKey entityKey; - private final EntityPersister descriptor; - private final Object entityInstance; - - public LoadingEntityEntry( - EntityInitializer entityInitializer, - EntityKey entityKey, - EntityPersister descriptor, - Object entityInstance) { - this.entityInitializer = entityInitializer; - this.entityKey = entityKey; - this.descriptor = descriptor; - this.entityInstance = entityInstance; - } - - public EntityInitializer getEntityInitializer() { - return entityInitializer; - } - - public EntityKey getEntityKey() { - return entityKey; - } - - public EntityPersister getDescriptor() { - return descriptor; - } - - public Object getEntityInstance() { - return entityInstance; - } - - @Override - public String toString() { - return String.format( - Locale.ROOT, - "LoadingEntityEntry(type=%s, id=%s)@%s", - getDescriptor().getEntityName(), - getEntityKey().getIdentifier(), - System.identityHashCode( this ) - ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/AbstractBatchEntitySelectFetchInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/AbstractBatchEntitySelectFetchInitializer.java index 2532a4bfa3..92ce681b44 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/AbstractBatchEntitySelectFetchInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/AbstractBatchEntitySelectFetchInitializer.java @@ -6,259 +6,227 @@ */ package org.hibernate.sql.results.graph.entity.internal; -import java.util.function.BiConsumer; - +import org.hibernate.Hibernate; import org.hibernate.engine.spi.EntityHolder; import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.EntityMappingType; -import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.LazyInitializer; import org.hibernate.spi.NavigablePath; -import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.graph.FetchParentAccess; +import org.hibernate.sql.results.graph.AssemblerCreationState; +import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.Initializer; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.entity.EntityInitializer; -import org.hibernate.sql.results.graph.internal.AbstractInitializer; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.checkerframework.checker.nullness.qual.Nullable; import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer; -public abstract class AbstractBatchEntitySelectFetchInitializer extends AbstractInitializer implements EntityInitializer { +public abstract class AbstractBatchEntitySelectFetchInitializer + extends EntitySelectFetchInitializer implements EntityInitializer { - protected final InitializerParent parent; - private final NavigablePath navigablePath; - private final boolean isPartOfKey; + protected final EntityInitializer owningEntityInitializer; - protected final EntityPersister concreteDescriptor; - protected final DomainResultAssembler identifierAssembler; - protected final ToOneAttributeMapping referencedModelPart; - protected final EntityInitializer owningEntityInitializer; + protected boolean batchDisabled; - // per-row state - protected @Nullable Object initializedEntityInstance; - protected @Nullable Object entityIdentifier; - protected @Nullable EntityKey entityKey; + public static abstract class AbstractBatchEntitySelectFetchInitializerData extends EntitySelectFetchInitializerData { + // per-row state + protected @Nullable EntityKey entityKey; - /** - * - * @deprecated Use {@link #AbstractBatchEntitySelectFetchInitializer(InitializerParent, ToOneAttributeMapping, NavigablePath, EntityPersister, DomainResultAssembler)} instead. - */ - @Deprecated(forRemoval = true) - public AbstractBatchEntitySelectFetchInitializer( - FetchParentAccess parent, - ToOneAttributeMapping referencedModelPart, - NavigablePath fetchedNavigable, - EntityPersister concreteDescriptor, - DomainResultAssembler identifierAssembler) { - this( - (InitializerParent) parent, - referencedModelPart, - fetchedNavigable, - concreteDescriptor, - identifierAssembler - ); + public AbstractBatchEntitySelectFetchInitializerData(RowProcessingState rowProcessingState) { + super( rowProcessingState ); + } } public AbstractBatchEntitySelectFetchInitializer( - InitializerParent parent, - ToOneAttributeMapping referencedModelPart, + InitializerParent parent, + ToOneAttributeMapping toOneMapping, NavigablePath fetchedNavigable, EntityPersister concreteDescriptor, - DomainResultAssembler identifierAssembler) { - this.parent = parent; - this.referencedModelPart = referencedModelPart; - this.navigablePath = fetchedNavigable; - this.isPartOfKey = Initializer.isPartOfKey( fetchedNavigable, parent ); - this.concreteDescriptor = concreteDescriptor; - this.identifierAssembler = identifierAssembler; - this.owningEntityInitializer = Initializer.findOwningEntityInitializer( parent ); + DomainResult keyResult, + AssemblerCreationState creationState) { + super( parent, toOneMapping, fetchedNavigable, concreteDescriptor, keyResult, creationState ); + //noinspection unchecked + this.owningEntityInitializer = (EntityInitializer) Initializer.findOwningEntityInitializer( parent ); assert owningEntityInitializer != null : "This initializer requires an owning parent entity initializer"; } - public ModelPart getInitializedPart() { - return referencedModelPart; + protected abstract void registerResolutionListener(Data data); + + @Override + public void startLoading(RowProcessingState rowProcessingState) { + batchDisabled = rowProcessingState.isScrollResult() + || !rowProcessingState + .getLoadQueryInfluencers() + .effectivelyBatchLoadable( toOneMapping.getEntityMappingType().getEntityPersister() ); + super.startLoading( rowProcessingState ); } @Override - public NavigablePath getNavigablePath() { - return navigablePath; - } - - @Override - public boolean isPartOfKey() { - return isPartOfKey; - } - - @Override - public boolean isResultInitializer() { - return false; - } - - protected abstract void registerResolutionListener(); - - @Override - public void resolveKey() { - if ( state != State.UNINITIALIZED ) { + public void resolveKey(Data data) { + if ( data.getState() != State.UNINITIALIZED ) { return; } - entityKey = null; - initializedEntityInstance = null; - final Initializer initializer = identifierAssembler.getInitializer(); + data.entityKey = null; + data.setInstance( null ); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + //noinspection unchecked + final Initializer initializer = (Initializer) keyAssembler.getInitializer(); if ( initializer != null ) { - initializer.resolveKey(); - entityIdentifier = null; - state = initializer.getState() == State.MISSING - ? State.MISSING - : State.KEY_RESOLVED; + final InitializerData subData = initializer.getData( rowProcessingState ); + initializer.resolveKey( subData ); + data.entityIdentifier = null; + data.setState( subData.getState() == State.MISSING ? State.MISSING : State.KEY_RESOLVED ); } else { - entityIdentifier = identifierAssembler.assemble( rowProcessingState ); - state = entityIdentifier == null - ? State.MISSING - : State.KEY_RESOLVED; + data.entityIdentifier = keyAssembler.assemble( rowProcessingState ); + data.setState( data.entityIdentifier == null ? State.MISSING : State.KEY_RESOLVED ); } } @Override - public void resolveInstance() { - if ( state != State.KEY_RESOLVED ) { + public void resolveInstance(Data data) { + if ( data.getState() != State.KEY_RESOLVED ) { return; } - state = State.RESOLVED; - if ( entityIdentifier == null ) { + data.setState( State.RESOLVED ); + final RowProcessingState initializerRowProcessingState = data.getRowProcessingState(); + if ( data.entityIdentifier == null ) { // entityIdentifier can be null if the identifier is based on an initializer - entityIdentifier = identifierAssembler.assemble( rowProcessingState ); - if ( entityIdentifier == null ) { - entityKey = null; - initializedEntityInstance = null; - state = State.MISSING; + data.entityIdentifier = keyAssembler.assemble( initializerRowProcessingState ); + if ( data.entityIdentifier == null ) { + data.entityKey = null; + data.setInstance( null ); + data.setState( State.MISSING ); return; } } - entityKey = new EntityKey( entityIdentifier, concreteDescriptor ); - initializedEntityInstance = getExistingInitializedInstance( rowProcessingState ); - if ( initializedEntityInstance == null ) { - // need to add the key to the batch queue only when the entity has not been already loaded or - // there isn't another initializer that is loading it - registerToBatchFetchQueue( rowProcessingState ); + if ( batchDisabled ) { + initialize( data ); + } + else { + data.entityKey = new EntityKey( data.entityIdentifier, concreteDescriptor ); + data.setInstance( getExistingInitializedInstance( data ) ); + if ( data.getInstance() == null ) { + // need to add the key to the batch queue only when the entity has not been already loaded or + // there isn't another initializer that is loading it + registerToBatchFetchQueue( data ); + } } } @Override - public void resolveInstance(Object instance) { + public void resolveInstance(Object instance, Data data) { if ( instance == null ) { - state = State.MISSING; - entityKey = null; - initializedEntityInstance = null; + data.setState( State.MISSING ); + data.entityKey = null; + data.setInstance( null ); return; } - final Initializer initializer = identifierAssembler.getInitializer(); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final Initializer initializer = keyAssembler.getInitializer(); // Only need to extract the identifier if the identifier has a many to one final boolean hasKeyManyToOne = initializer != null; - final SharedSessionContractImplementor session = rowProcessingState.getSession(); final LazyInitializer lazyInitializer = extractLazyInitializer( instance ); - entityKey = null; + data.entityKey = null; if ( lazyInitializer == null ) { // Entity is initialized - state = State.INITIALIZED; + data.setState( State.INITIALIZED ); if ( hasKeyManyToOne ) { - entityIdentifier = concreteDescriptor.getIdentifier( instance, session ); + data.entityIdentifier = concreteDescriptor.getIdentifier( instance, rowProcessingState.getSession() ); } - initializedEntityInstance = instance; + data.setInstance( instance ); } else if ( lazyInitializer.isUninitialized() ) { - state = State.RESOLVED; + data.setState( State.RESOLVED ); if ( hasKeyManyToOne ) { - entityIdentifier = lazyInitializer.getIdentifier(); + data.entityIdentifier = lazyInitializer.getIdentifier(); } // Resolve and potentially create the entity instance - registerToBatchFetchQueue( rowProcessingState ); + registerToBatchFetchQueue( data ); } else { // Entity is initialized - state = State.INITIALIZED; + data.setState( State.INITIALIZED ); if ( hasKeyManyToOne ) { - entityIdentifier = lazyInitializer.getIdentifier(); + data.entityIdentifier = lazyInitializer.getIdentifier(); } - initializedEntityInstance = lazyInitializer.getImplementation(); + data.setInstance( lazyInitializer.getImplementation() ); } if ( hasKeyManyToOne ) { - initializer.resolveInstance( entityIdentifier ); + initializer.resolveInstance( data.entityIdentifier, rowProcessingState ); } - else if ( !rowProcessingState.isQueryCacheHit() && rowProcessingState.getQueryOptions().isResultCachingEnabled() == Boolean.TRUE ) { + else if ( rowProcessingState.needsResolveState() ) { // Resolve the state of the identifier if result caching is enabled and this is not a query cache hit - identifierAssembler.resolveState( rowProcessingState ); + keyAssembler.resolveState( rowProcessingState ); } } - protected Object getExistingInitializedInstance(RowProcessingState rowProcessingState) { - final SharedSessionContractImplementor session = rowProcessingState.getSession(); + @Override + public void initializeInstance(Data data) { + if ( data.getState() != State.RESOLVED ) { + return; + } + data.setState( State.INITIALIZED ); + if ( batchDisabled ) { + Hibernate.initialize( data.getInstance() ); + } + } + + protected Object getExistingInitializedInstance(Data data) { + final SharedSessionContractImplementor session = data.getRowProcessingState().getSession(); final PersistenceContext persistenceContext = session.getPersistenceContext(); - final EntityHolder holder = persistenceContext.getEntityHolder( entityKey ); + final EntityHolder holder = persistenceContext.getEntityHolder( data.entityKey ); if ( holder != null && holder.getEntity() != null && holder.isEventuallyInitialized() ) { return holder.getEntity(); } // we need to register a resolution listener only if there is not an already initialized instance // or an instance that another initializer is loading - registerResolutionListener(); + registerResolutionListener( data ); return null; } - protected void registerToBatchFetchQueue(RowProcessingState rowProcessingState) { - assert entityKey != null; - rowProcessingState.getSession().getPersistenceContext() - .getBatchFetchQueue().addBatchLoadableEntityKey( entityKey ); + protected void registerToBatchFetchQueue(Data data) { + assert data.entityKey != null; + data.getRowProcessingState().getSession().getPersistenceContext() + .getBatchFetchQueue().addBatchLoadableEntityKey( data.entityKey ); } @Override - public void initializeInstanceFromParent(Object parentInstance) { + public void initializeInstanceFromParent(Object parentInstance, Data data) { final AttributeMapping attributeMapping = getInitializedPart().asAttributeMapping(); final Object instance = attributeMapping != null ? attributeMapping.getValue( parentInstance ) : parentInstance; // No need to initialize these fields - entityKey = null; - initializedEntityInstance = null; + data.entityKey = null; + data.setInstance( null ); if ( instance == null ) { - state = State.MISSING; + data.setState( State.MISSING ); } else { final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( instance ); if ( lazyInitializer != null && lazyInitializer.isUninitialized() ) { - entityKey = new EntityKey( lazyInitializer.getIdentifier(), concreteDescriptor ); - registerToBatchFetchQueue( rowProcessingState ); + data.entityKey = new EntityKey( lazyInitializer.getIdentifier(), concreteDescriptor ); + registerToBatchFetchQueue( data ); } - state = State.INITIALIZED; + data.setState( State.INITIALIZED ); } } @Override - protected void forEachSubInitializer(BiConsumer consumer, X arg) { - final Initializer initializer = identifierAssembler.getInitializer(); - if ( initializer != null ) { - consumer.accept( initializer, arg ); - } - } - - @Override - public EntityPersister getEntityDescriptor() { - return concreteDescriptor; - } - - @Override - public Object getEntityInstance() { - return state == State.RESOLVED || state == State.INITIALIZED ? initializedEntityInstance : null; + public Object getEntityInstance(Data data) { + return data.getState() == State.RESOLVED || data.getState() == State.INITIALIZED ? data.getInstance() : null; } protected static Object loadInstance( @@ -282,13 +250,13 @@ public abstract class AbstractBatchEntitySelectFetchInitializer extends Abstract ]; parentEntityAttributes[entityDescriptor.getSubclassId()] = getParentEntityAttribute( entityDescriptor, - referencedModelPart, + toOneMapping, attributeName ); for ( EntityMappingType subMappingType : entityDescriptor.getSubMappingTypes() ) { parentEntityAttributes[subMappingType.getSubclassId()] = getParentEntityAttribute( subMappingType, - referencedModelPart, + toOneMapping, attributeName ); } @@ -309,31 +277,4 @@ public abstract class AbstractBatchEntitySelectFetchInitializer extends Abstract return null; } - @Override - public FetchParentAccess getFetchParentAccess() { - return (FetchParentAccess) parent; - } - - @Override - public InitializerParent getParent() { - return parent; - } - - @Override - public EntityPersister getConcreteDescriptor() { - return concreteDescriptor; - } - - @Override - public EntityKey getEntityKey() { - throw new UnsupportedOperationException( - "This should never happen, because this initializer has not child initializers" ); - } - - @Override - public Object getParentKey() { - throw new UnsupportedOperationException( - "This should never happen, because this initializer has not child initializers" ); - } - } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/AbstractNonJoinedEntityFetch.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/AbstractNonJoinedEntityFetch.java index be1b909634..7b504a796e 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/AbstractNonJoinedEntityFetch.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/AbstractNonJoinedEntityFetch.java @@ -17,7 +17,6 @@ import org.hibernate.sql.results.graph.DomainResultAssembler; 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.FetchParentAccess; import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.InitializerProducer; @@ -143,33 +142,26 @@ public abstract class AbstractNonJoinedEntityFetch implements EntityFetch, @Override public DomainResultAssembler createAssembler( - FetchParentAccess parentAccess, + InitializerParent parent, AssemblerCreationState creationState) { - return createAssembler( (InitializerParent) parentAccess, creationState ); - } - - @Override - public DomainResultAssembler createAssembler( - InitializerParent parent, - AssemblerCreationState creationState) { - final EntityInitializer entityInitializer = creationState.resolveInitializer( this, parent, this ) + final EntityInitializer entityInitializer = creationState.resolveInitializer( this, parent, this ) .asEntityInitializer(); assert entityInitializer != null; return buildEntityAssembler( entityInitializer ); } @Override - public EntityInitializer createInitializer( + public EntityInitializer createInitializer( AbstractNonJoinedEntityFetch resultGraphNode, - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return resultGraphNode.createInitializer( parent, creationState ); } @Override - public abstract EntityInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState); + public abstract EntityInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState); - protected EntityAssembler buildEntityAssembler(EntityInitializer entityInitializer) { + protected EntityAssembler buildEntityAssembler(EntityInitializer entityInitializer) { return new EntityAssembler( getFetchedMapping().getJavaType(), entityInitializer ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchEntityInsideEmbeddableSelectFetchInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchEntityInsideEmbeddableSelectFetchInitializer.java index d1d5a06bdf..6c0ba73a66 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchEntityInsideEmbeddableSelectFetchInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchEntityInsideEmbeddableSelectFetchInitializer.java @@ -24,16 +24,15 @@ import org.hibernate.persister.entity.EntityPersister; import org.hibernate.property.access.spi.Getter; import org.hibernate.property.access.spi.Setter; import org.hibernate.spi.NavigablePath; -import org.hibernate.sql.exec.spi.ExecutionContext; -import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.graph.FetchParentAccess; +import org.hibernate.sql.results.graph.AssemblerCreationState; +import org.hibernate.sql.results.graph.DomainResult; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.entity.EntityInitializer; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.Type; -public class BatchEntityInsideEmbeddableSelectFetchInitializer extends AbstractBatchEntitySelectFetchInitializer { - private Map> toBatchLoad; +public class BatchEntityInsideEmbeddableSelectFetchInitializer extends AbstractBatchEntitySelectFetchInitializer { protected final Setter referencedModelPartSetter; protected final AttributeMapping[] rootEmbeddableAttributes; protected final Getter[] rootEmbeddableGetters; @@ -54,32 +53,22 @@ public class BatchEntityInsideEmbeddableSelectFetchInitializer extends AbstractB } }; - /** - * @deprecated Use {@link #BatchEntityInsideEmbeddableSelectFetchInitializer(InitializerParent, ToOneAttributeMapping, NavigablePath, EntityPersister, DomainResultAssembler)} instead. - */ - @Deprecated(forRemoval = true) - public BatchEntityInsideEmbeddableSelectFetchInitializer( - FetchParentAccess parentAccess, - ToOneAttributeMapping referencedModelPart, - NavigablePath fetchedNavigable, - EntityPersister concreteDescriptor, - DomainResultAssembler identifierAssembler) { - this( - (InitializerParent) parentAccess, - referencedModelPart, - fetchedNavigable, - concreteDescriptor, - identifierAssembler - ); + public static class BatchEntityInsideEmbeddableSelectFetchInitializerData extends AbstractBatchEntitySelectFetchInitializerData { + private Map> toBatchLoad; + + public BatchEntityInsideEmbeddableSelectFetchInitializerData(RowProcessingState rowProcessingState) { + super( rowProcessingState ); + } } public BatchEntityInsideEmbeddableSelectFetchInitializer( - InitializerParent parentAccess, + InitializerParent parentAccess, ToOneAttributeMapping referencedModelPart, NavigablePath fetchedNavigable, EntityPersister concreteDescriptor, - DomainResultAssembler identifierAssembler) { - super( parentAccess, referencedModelPart, fetchedNavigable, concreteDescriptor, identifierAssembler ); + DomainResult keyResult, + AssemblerCreationState creationState) { + super( parentAccess, referencedModelPart, fetchedNavigable, concreteDescriptor, keyResult, creationState ); this.referencedModelPartSetter = referencedModelPart.getAttributeMetadata().getPropertyAccess().getSetter(); final String rootEmbeddablePropertyName = getRootEmbeddablePropertyName( @@ -98,6 +87,11 @@ public class BatchEntityInsideEmbeddableSelectFetchInitializer extends AbstractB this.rootEmbeddablePropertyTypes = getParentEntityAttributeTypes( rootEmbeddablePropertyName ); } + @Override + protected InitializerData createInitializerData(RowProcessingState rowProcessingState) { + return new BatchEntityInsideEmbeddableSelectFetchInitializerData( rowProcessingState ); + } + protected Type[] getParentEntityAttributeTypes(String attributeName) { final EntityPersister entityDescriptor = owningEntityInitializer.getEntityDescriptor(); final Type[] attributeTypes = new Type[ @@ -119,43 +113,38 @@ public class BatchEntityInsideEmbeddableSelectFetchInitializer extends AbstractB } @Override - protected void registerToBatchFetchQueue(RowProcessingState rowProcessingState) { - super.registerToBatchFetchQueue( rowProcessingState ); - initializedEntityInstance = BATCH_PROPERTY; + protected void registerToBatchFetchQueue(BatchEntityInsideEmbeddableSelectFetchInitializerData data) { + super.registerToBatchFetchQueue( data ); + data.setInstance( BATCH_PROPERTY ); } @Override - public void initializeInstance() { - super.initializeInstance(); + public void initializeInstance(BatchEntityInsideEmbeddableSelectFetchInitializerData data) { + super.initializeInstance( data ); // todo: check why this can't be moved to #registerToBatchFetchQueue - if ( initializedEntityInstance == BATCH_PROPERTY ) { - final int owningEntitySubclassId = owningEntityInitializer.getConcreteDescriptor().getSubclassId(); + if ( data.getInstance() == BATCH_PROPERTY ) { + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final InitializerData owningData = owningEntityInitializer.getData( rowProcessingState ); + final int owningEntitySubclassId = owningEntityInitializer.getConcreteDescriptor( owningData ).getSubclassId(); final AttributeMapping rootEmbeddableAttribute = rootEmbeddableAttributes[owningEntitySubclassId]; if ( rootEmbeddableAttribute != null ) { - getParentInfos().add( new ParentInfo( - owningEntityInitializer.getTargetInstance(), - parent.getInitializedInstance(), - rootEmbeddableAttribute.getStateArrayPosition(), - owningEntitySubclassId - ) ); + if ( data.toBatchLoad == null ) { + data.toBatchLoad = new HashMap<>(); + } + data.toBatchLoad.computeIfAbsent( data.entityKey, key -> new ArrayList<>() ).add( + new ParentInfo( + owningEntityInitializer.getTargetInstance( owningData ), + parent.getResolvedInstance( rowProcessingState ), + rootEmbeddableAttribute.getStateArrayPosition(), + owningEntitySubclassId + ) + ); } } } @Override - protected void registerResolutionListener() { - } - - private List getParentInfos() { - if ( toBatchLoad == null ) { - toBatchLoad = new HashMap<>(); - } - return toBatchLoad.computeIfAbsent( entityKey, key -> new ArrayList<>() ); - } - - @Override - public boolean isEntityInitialized() { - return false; + protected void registerResolutionListener(BatchEntityInsideEmbeddableSelectFetchInitializerData data) { } private static class ParentInfo { @@ -177,13 +166,13 @@ public class BatchEntityInsideEmbeddableSelectFetchInitializer extends AbstractB } @Override - public void endLoading(ExecutionContext executionContext) { - super.endLoading( executionContext ); - if ( toBatchLoad != null ) { - toBatchLoad.forEach( + public void endLoading(BatchEntityInsideEmbeddableSelectFetchInitializerData data) { + super.endLoading( data ); + if ( data.toBatchLoad != null ) { + data.toBatchLoad.forEach( (entityKey, parentInfos) -> { - final SharedSessionContractImplementor session = executionContext.getSession(); - final Object loadedInstance = loadInstance( entityKey, referencedModelPart, session ); + final SharedSessionContractImplementor session = data.getRowProcessingState().getSession(); + final Object loadedInstance = loadInstance( entityKey, toOneMapping, session ); for ( ParentInfo parentInfo : parentInfos ) { final PersistenceContext persistenceContext = session.getPersistenceContext(); final EntityEntry parentEntityEntry = persistenceContext.getEntry( parentInfo.parentEntityInstance ); @@ -206,75 +195,13 @@ public class BatchEntityInsideEmbeddableSelectFetchInitializer extends AbstractB } } ); - toBatchLoad.clear(); + data.toBatchLoad.clear(); } } - protected static void setInstance( - EntityInitializer entityInitializer, - ToOneAttributeMapping referencedModelPart, - String rootEmbeddablePropertyName, - int propertyIndex, - Object loadedInstance, - Object embeddableParentInstance, - Object parentEntity, - EntityEntry parentEntityEntry, - SharedSessionContractImplementor session) { - referencedModelPart.getPropertyAccess().getSetter().set( embeddableParentInstance, loadedInstance ); - updateRootEntityLoadedState( - entityInitializer, - rootEmbeddablePropertyName, - propertyIndex, - parentEntity, - parentEntityEntry, - session - ); - } - - private static void updateRootEntityLoadedState( - EntityInitializer entityInitializer, - String rootEmbeddablePropertyName, - int propertyIndex, - Object parentEntity, - EntityEntry parentEntityEntry, - SharedSessionContractImplementor session) { - Object[] loadedState = parentEntityEntry.getLoadedState(); - if ( loadedState != null ) { - /* - E.g. - - ParentEntity -> RootEmbeddable -> ParentEmbeddable -> toOneAttributeMapping - - The value of RootEmbeddable is needed to update the ParentEntity loaded state - */ - final EntityPersister entityDescriptor = entityInitializer.getEntityDescriptor(); - final Object rootEmbeddable = entityDescriptor.getPropertyValue( - parentEntity, - rootEmbeddablePropertyName - ); - loadedState[propertyIndex] = entityDescriptor.getPropertyType( rootEmbeddablePropertyName ) - .deepCopy( rootEmbeddable, session.getFactory() ); - } - } - - /** - * @deprecated Use {@link #getRootEmbeddablePropertyName(EntityInitializer, InitializerParent, ToOneAttributeMapping)} instead. - */ - @Deprecated(forRemoval = true) protected static String getRootEmbeddablePropertyName( - EntityInitializer firstEntityInitializer, - FetchParentAccess parentAccess, - ToOneAttributeMapping referencedModelPart) { - return getRootEmbeddablePropertyName( - firstEntityInitializer, - (InitializerParent) parentAccess, - referencedModelPart - ); - } - - protected static String getRootEmbeddablePropertyName( - EntityInitializer firstEntityInitializer, - InitializerParent parent, + EntityInitializer firstEntityInitializer, + InitializerParent parent, ToOneAttributeMapping referencedModelPart) { final NavigablePath entityPath = firstEntityInitializer.getNavigablePath(); NavigablePath navigablePath = parent.getNavigablePath(); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchEntitySelectFetchInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchEntitySelectFetchInitializer.java index 3832e994b6..9f86dd537c 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchEntitySelectFetchInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchEntitySelectFetchInitializer.java @@ -20,70 +20,64 @@ import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.property.access.spi.Setter; import org.hibernate.spi.NavigablePath; -import org.hibernate.sql.exec.spi.ExecutionContext; -import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.graph.FetchParentAccess; +import org.hibernate.sql.results.graph.AssemblerCreationState; +import org.hibernate.sql.results.graph.DomainResult; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.InitializerParent; +import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.Type; -public class BatchEntitySelectFetchInitializer extends AbstractBatchEntitySelectFetchInitializer { +public class BatchEntitySelectFetchInitializer extends AbstractBatchEntitySelectFetchInitializer { protected final AttributeMapping[] parentAttributes; protected final Setter referencedModelPartSetter; protected final Type referencedModelPartType; - private Map> toBatchLoad; + public static class BatchEntitySelectFetchInitializerData extends AbstractBatchEntitySelectFetchInitializerData { + private Map> toBatchLoad; - /** - * @deprecated Use {@link #BatchEntitySelectFetchInitializer(InitializerParent, ToOneAttributeMapping, NavigablePath, EntityPersister, DomainResultAssembler)} instead. - */ - @Deprecated(forRemoval = true) - public BatchEntitySelectFetchInitializer( - FetchParentAccess parentAccess, - ToOneAttributeMapping referencedModelPart, - NavigablePath fetchedNavigable, - EntityPersister concreteDescriptor, - DomainResultAssembler identifierAssembler) { - this( - (InitializerParent) parentAccess, - referencedModelPart, - fetchedNavigable, - concreteDescriptor, - identifierAssembler - ); + public BatchEntitySelectFetchInitializerData(RowProcessingState rowProcessingState) { + super( rowProcessingState ); + } } public BatchEntitySelectFetchInitializer( - InitializerParent parentAccess, + InitializerParent parentAccess, ToOneAttributeMapping referencedModelPart, NavigablePath fetchedNavigable, EntityPersister concreteDescriptor, - DomainResultAssembler identifierAssembler) { - super( parentAccess, referencedModelPart, fetchedNavigable, concreteDescriptor, identifierAssembler ); + DomainResult keyResult, + AssemblerCreationState creationState) { + super( parentAccess, referencedModelPart, fetchedNavigable, concreteDescriptor, keyResult, creationState ); this.parentAttributes = getParentEntityAttributes( referencedModelPart.getAttributeName() ); this.referencedModelPartSetter = referencedModelPart.getPropertyAccess().getSetter(); - this.referencedModelPartType = owningEntityInitializer.getEntityDescriptor().getPropertyType( referencedModelPart.getAttributeName() ); + this.referencedModelPartType = referencedModelPart.findContainingEntityMapping().getEntityPersister() + .getPropertyType( referencedModelPart.getAttributeName() ); } @Override - protected void registerResolutionListener() { + protected InitializerData createInitializerData(RowProcessingState rowProcessingState) { + return new BatchEntitySelectFetchInitializerData( rowProcessingState ); + } + + @Override + protected void registerResolutionListener(BatchEntitySelectFetchInitializerData data) { + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final InitializerData owningData = owningEntityInitializer.getData( rowProcessingState ); final AttributeMapping parentAttribute; - if ( !owningEntityInitializer.isEntityInitialized() && ( parentAttribute = parentAttributes[owningEntityInitializer.getConcreteDescriptor().getSubclassId()] ) != null ) { - getParentInfos().add( new ParentInfo( owningEntityInitializer.getTargetInstance(), parentAttribute.getStateArrayPosition() ) ); + if ( owningData.getState() != State.INITIALIZED + && ( parentAttribute = parentAttributes[owningEntityInitializer.getConcreteDescriptor( owningData ).getSubclassId()] ) != null ) { + if ( data.toBatchLoad == null ) { + data.toBatchLoad = new HashMap<>(); + } + data.toBatchLoad.computeIfAbsent( data.entityKey, key -> new ArrayList<>() ).add( + new ParentInfo( + owningEntityInitializer.getTargetInstance( owningData ), + parentAttribute.getStateArrayPosition() + ) + ); } } - private List getParentInfos() { - if ( toBatchLoad == null ) { - toBatchLoad = new HashMap<>(); - } - return toBatchLoad.computeIfAbsent( entityKey, key -> new ArrayList<>() ); - } - - @Override - public boolean isEntityInitialized() { - return false; - } - private static class ParentInfo { private final Object parentInstance; private final int propertyIndex; @@ -95,13 +89,13 @@ public class BatchEntitySelectFetchInitializer extends AbstractBatchEntitySelect } @Override - public void endLoading(ExecutionContext executionContext) { - super.endLoading( executionContext ); - if ( toBatchLoad != null ) { - toBatchLoad.forEach( + public void endLoading(BatchEntitySelectFetchInitializerData data) { + super.endLoading( data ); + if ( data.toBatchLoad != null ) { + data.toBatchLoad.forEach( (entityKey, parentInfos) -> { - final SharedSessionContractImplementor session = executionContext.getSession(); - final Object instance = loadInstance( entityKey, referencedModelPart, session ); + final SharedSessionContractImplementor session = data.getRowProcessingState().getSession(); + final Object instance = loadInstance( entityKey, toOneMapping, session ); for ( ParentInfo parentInfo : parentInfos ) { final Object parentInstance = parentInfo.parentInstance; final EntityEntry entry = session.getPersistenceContext().getEntry( parentInstance ); @@ -116,7 +110,7 @@ public class BatchEntitySelectFetchInitializer extends AbstractBatchEntitySelect } } ); - toBatchLoad.clear(); + data.toBatchLoad.clear(); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchInitializeEntitySelectFetchInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchInitializeEntitySelectFetchInitializer.java index 9e0a50a939..330f0d8b29 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchInitializeEntitySelectFetchInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/BatchInitializeEntitySelectFetchInitializer.java @@ -15,9 +15,9 @@ import org.hibernate.internal.log.LoggingHelper; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.spi.NavigablePath; -import org.hibernate.sql.exec.spi.ExecutionContext; -import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.graph.FetchParentAccess; +import org.hibernate.sql.results.graph.AssemblerCreationState; +import org.hibernate.sql.results.graph.DomainResult; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; @@ -25,69 +25,57 @@ import org.hibernate.sql.results.jdbc.spi.RowProcessingState; * Loads entities from the persistence context or creates proxies if not found there, * and initializes all proxies in a batch. */ -public class BatchInitializeEntitySelectFetchInitializer extends AbstractBatchEntitySelectFetchInitializer { +public class BatchInitializeEntitySelectFetchInitializer extends AbstractBatchEntitySelectFetchInitializer { - private final Set toBatchLoad = new HashSet<>(); + public static class BatchInitializeEntitySelectFetchInitializerData extends AbstractBatchEntitySelectFetchInitializerData { + private final Set toBatchLoad = new HashSet<>(); - /** - * @deprecated Use {@link #BatchInitializeEntitySelectFetchInitializer(InitializerParent, ToOneAttributeMapping, NavigablePath, EntityPersister, DomainResultAssembler)} instead. - */ - @Deprecated(forRemoval = true) - public BatchInitializeEntitySelectFetchInitializer( - FetchParentAccess parentAccess, - ToOneAttributeMapping referencedModelPart, - NavigablePath fetchedNavigable, - EntityPersister concreteDescriptor, - DomainResultAssembler identifierAssembler) { - this( - (InitializerParent) parentAccess, - referencedModelPart, - fetchedNavigable, - concreteDescriptor, - identifierAssembler - ); + public BatchInitializeEntitySelectFetchInitializerData(RowProcessingState rowProcessingState) { + super( rowProcessingState ); + } } public BatchInitializeEntitySelectFetchInitializer( - InitializerParent parent, + InitializerParent parent, ToOneAttributeMapping referencedModelPart, NavigablePath fetchedNavigable, EntityPersister concreteDescriptor, - DomainResultAssembler identifierAssembler) { - super( parent, referencedModelPart, fetchedNavigable, concreteDescriptor, identifierAssembler ); + DomainResult keyResult, + AssemblerCreationState creationState) { + super( parent, referencedModelPart, fetchedNavigable, concreteDescriptor, keyResult, creationState ); } @Override - protected void registerResolutionListener() { + protected InitializerData createInitializerData(RowProcessingState rowProcessingState) { + return new BatchInitializeEntitySelectFetchInitializerData( rowProcessingState ); + } + + @Override + protected void registerResolutionListener(BatchInitializeEntitySelectFetchInitializerData data) { // No-op, because we resolve a proxy } @Override - protected void registerToBatchFetchQueue(RowProcessingState rowProcessingState) { - super.registerToBatchFetchQueue( rowProcessingState ); + protected void registerToBatchFetchQueue(BatchInitializeEntitySelectFetchInitializerData data) { + super.registerToBatchFetchQueue( data ); // Force creating a proxy - initializedEntityInstance = rowProcessingState.getSession().internalLoad( - entityKey.getEntityName(), - entityKey.getIdentifier(), + data.setInstance( data.getRowProcessingState().getSession().internalLoad( + data.entityKey.getEntityName(), + data.entityKey.getIdentifier(), false, false - ); - toBatchLoad.add( entityKey ); + ) ); + data.toBatchLoad.add( data.entityKey ); } @Override - public boolean isEntityInitialized() { - return state == State.INITIALIZED; - } - - @Override - public void endLoading(ExecutionContext executionContext) { - super.endLoading( executionContext ); - final SharedSessionContractImplementor session = executionContext.getSession(); - for ( EntityKey key : toBatchLoad ) { - loadInstance( key, referencedModelPart, session ); + public void endLoading(BatchInitializeEntitySelectFetchInitializerData data) { + super.endLoading( data ); + final SharedSessionContractImplementor session = data.getRowProcessingState().getSession(); + for ( EntityKey key : data.toBatchLoad ) { + loadInstance( key, toOneMapping, session ); } - toBatchLoad.clear(); + data.toBatchLoad.clear(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/DiscriminatedEntityFetch.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/DiscriminatedEntityFetch.java index c659758380..48c3783bff 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/DiscriminatedEntityFetch.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/DiscriminatedEntityFetch.java @@ -14,7 +14,6 @@ import org.hibernate.sql.results.graph.DomainResultAssembler; 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.FetchParentAccess; import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.InitializerProducer; @@ -62,14 +61,7 @@ public class DiscriminatedEntityFetch extends AbstractDiscriminatedEntityResultG @Override public DomainResultAssembler createAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createAssembler( (InitializerParent) parentAccess, creationState ); - } - - @Override - public DomainResultAssembler createAssembler( - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return new EntityAssembler( getReferencedMappingContainer().getJavaType(), @@ -78,15 +70,15 @@ public class DiscriminatedEntityFetch extends AbstractDiscriminatedEntityResultG } @Override - public Initializer createInitializer( + public Initializer createInitializer( DiscriminatedEntityFetch resultGraphNode, - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return resultGraphNode.createInitializer( parent, creationState ); } @Override - public Initializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { + public Initializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { return new DiscriminatedEntityInitializer( parent, getReferencedMappingType(), diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/DiscriminatedEntityInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/DiscriminatedEntityInitializer.java index dea6622698..fab8b9df6a 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/DiscriminatedEntityInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/DiscriminatedEntityInitializer.java @@ -14,7 +14,6 @@ import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.log.LoggingHelper; -import org.hibernate.internal.util.StringHelper; import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.DiscriminatedAssociationModelPart; import org.hibernate.metamodel.mapping.ModelPart; @@ -24,12 +23,12 @@ import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Fetch; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Initializer; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.entity.EntityInitializer; -import org.hibernate.sql.results.graph.entity.EntityLoadingLogging; import org.hibernate.sql.results.graph.internal.AbstractInitializer; +import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.checkerframework.checker.nullness.qual.Nullable; @@ -39,10 +38,12 @@ import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer; /** * Initializer for discriminated mappings. */ -public class DiscriminatedEntityInitializer extends AbstractInitializer implements EntityInitializer { +public class DiscriminatedEntityInitializer + extends AbstractInitializer + implements EntityInitializer { private static final String CONCRETE_NAME = DiscriminatedEntityInitializer.class.getSimpleName(); - protected final InitializerParent parent; + protected final InitializerParent parent; private final NavigablePath navigablePath; private final boolean isPartOfKey; @@ -52,38 +53,17 @@ public class DiscriminatedEntityInitializer extends AbstractInitializer implemen private final boolean eager; private final boolean resultInitializer; - // per-row state - protected EntityPersister concreteDescriptor; - protected Object entityIdentifier; - protected Object entityInstance; + public static class DiscriminatedEntityInitializerData extends InitializerData { + protected EntityPersister concreteDescriptor; + protected Object entityIdentifier; - /** - * @deprecated Use {@link #DiscriminatedEntityInitializer(InitializerParent, DiscriminatedAssociationModelPart, NavigablePath, Fetch, Fetch, boolean, boolean, AssemblerCreationState)} instead. - */ - @Deprecated(forRemoval = true) - public DiscriminatedEntityInitializer( - FetchParentAccess parent, - DiscriminatedAssociationModelPart fetchedPart, - NavigablePath fetchedNavigable, - Fetch discriminatorFetch, - Fetch keyFetch, - boolean eager, - boolean resultInitializer, - AssemblerCreationState creationState) { - this( - (InitializerParent) parent, - fetchedPart, - fetchedNavigable, - discriminatorFetch, - keyFetch, - eager, - resultInitializer, - creationState - ); + public DiscriminatedEntityInitializerData(RowProcessingState rowProcessingState) { + super( rowProcessingState ); + } } public DiscriminatedEntityInitializer( - InitializerParent parent, + InitializerParent parent, DiscriminatedAssociationModelPart fetchedPart, NavigablePath fetchedNavigable, Fetch discriminatorFetch, @@ -91,23 +71,24 @@ public class DiscriminatedEntityInitializer extends AbstractInitializer implemen boolean eager, boolean resultInitializer, AssemblerCreationState creationState) { + super( creationState ); this.parent = parent; this.fetchedPart = fetchedPart; this.navigablePath = fetchedNavigable; this.isPartOfKey = Initializer.isPartOfKey( fetchedNavigable, parent ); - this.discriminatorValueAssembler = discriminatorFetch.createAssembler( (InitializerParent) this, creationState ); - this.keyValueAssembler = keyFetch.createAssembler( (InitializerParent) this, creationState ); + this.discriminatorValueAssembler = discriminatorFetch.createAssembler( this, creationState ); + this.keyValueAssembler = keyFetch.createAssembler( this, creationState ); this.eager = eager; this.resultInitializer = resultInitializer; } @Override - public FetchParentAccess getFetchParentAccess() { - return (FetchParentAccess) parent; + protected InitializerData createInitializerData(RowProcessingState rowProcessingState) { + return new DiscriminatedEntityInitializerData( rowProcessingState ); } @Override - public @Nullable InitializerParent getParent() { + public @Nullable InitializerParent getParent() { return parent; } @@ -121,130 +102,105 @@ public class DiscriminatedEntityInitializer extends AbstractInitializer implemen } @Override - public void resolveKey() { - if ( state != State.UNINITIALIZED ) { + public void resolveKey(DiscriminatedEntityInitializerData data) { + if ( data.getState() != State.UNINITIALIZED ) { return; } // resolve the key and the discriminator, and then use those to load the indicated entity - final Object discriminatorValue = discriminatorValueAssembler.assemble( rowProcessingState ); + final Object discriminatorValue = discriminatorValueAssembler.assemble( data.getRowProcessingState() ); if ( discriminatorValue == null ) { - state = State.MISSING; - concreteDescriptor = null; - entityIdentifier = null; - entityInstance = null; + data.setState( State.MISSING ); + data.concreteDescriptor = null; + data.entityIdentifier = null; + data.setInstance( null ); // null association - assert keyValueAssembler.assemble( rowProcessingState ) == null; + assert keyValueAssembler.assemble( data.getRowProcessingState() ) == null; } else { - state = State.KEY_RESOLVED; - concreteDescriptor = fetchedPart.resolveDiscriminatorValue( discriminatorValue ).getEntityPersister(); - entityIdentifier = keyValueAssembler.assemble( rowProcessingState ); + data.setState( State.KEY_RESOLVED ); + data.concreteDescriptor = fetchedPart.resolveDiscriminatorValue( discriminatorValue ).getEntityPersister(); + data.entityIdentifier = keyValueAssembler.assemble( data.getRowProcessingState() ); } } @Override - public void resolveInstance() { - if ( state != State.KEY_RESOLVED ) { + public void resolveInstance(DiscriminatedEntityInitializerData data) { + if ( data.getState() != State.KEY_RESOLVED ) { return; } - state = State.INITIALIZED; + data.setState( State.INITIALIZED ); - if ( EntityLoadingLogging.ENTITY_LOADING_LOGGER.isTraceEnabled() ) { - EntityLoadingLogging.ENTITY_LOADING_LOGGER.tracef( - "(%s) Beginning Initializer#resolveInstance process for entity (%s) : %s", - StringHelper.collapse( this.getClass().getName() ), - getNavigablePath(), - entityIdentifier - ); - } - final SharedSessionContractImplementor session = rowProcessingState.getSession(); - final EntityKey entityKey = new EntityKey( entityIdentifier, concreteDescriptor ); + final SharedSessionContractImplementor session = data.getRowProcessingState().getSession(); + final EntityKey entityKey = new EntityKey( data.entityIdentifier, data.concreteDescriptor ); final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); final EntityHolder holder = persistenceContext.getEntityHolder( entityKey ); if ( holder != null ) { - if ( EntityLoadingLogging.ENTITY_LOADING_LOGGER.isDebugEnabled() ) { - EntityLoadingLogging.ENTITY_LOADING_LOGGER.debugf( - "(%s) Found existing loading entry [%s] - using loading instance", - CONCRETE_NAME, - toLoggableString( - getNavigablePath(), - entityIdentifier - ) - ); - } - entityInstance = holder.getEntity(); + data.setInstance( holder.getEntity() ); if ( holder.getEntityInitializer() == null ) { - if ( entityInstance != null && Hibernate.isInitialized( entityInstance ) ) { + if ( data.getInstance() != null && Hibernate.isInitialized( data.getInstance() ) ) { return; } } else if ( holder.getEntityInitializer() != this ) { // the entity is already being loaded elsewhere - if ( EntityLoadingLogging.ENTITY_LOADING_LOGGER.isDebugEnabled() ) { - EntityLoadingLogging.ENTITY_LOADING_LOGGER.debugf( - "(%s) Entity [%s] being loaded by another initializer [%s] - skipping processing", - CONCRETE_NAME, - toLoggableString( getNavigablePath(), entityIdentifier ), - holder.getEntityInitializer() - ); - } return; } - else if ( entityInstance == null ) { + else if ( data.getInstance() == null ) { // todo: maybe mark this as resolved instead? assert holder.getProxy() == null : "How to handle this case?"; return; } } - entityInstance = rowProcessingState.getSession().internalLoad( - concreteDescriptor.getEntityName(), - entityIdentifier, + data.setInstance( session.internalLoad( + data.concreteDescriptor.getEntityName(), + data.entityIdentifier, eager, // should not be null since we checked already. null would indicate bad data (ala, not-found handling) false - ); + ) ); } @Override - public void resolveInstance(Object instance) { + public void resolveInstance(Object instance, DiscriminatedEntityInitializerData data) { if ( instance == null ) { - state = State.MISSING; - entityIdentifier = null; - concreteDescriptor = null; - entityInstance = null; + data.setState( State.MISSING ); + data.entityIdentifier = null; + data.concreteDescriptor = null; + data.setInstance( null ); } else { + final RowProcessingState rowProcessingState = data.getRowProcessingState(); final SharedSessionContractImplementor session = rowProcessingState.getSession(); - final LazyInitializer lazyInitializer = extractLazyInitializer( entityInstance ); + final LazyInitializer lazyInitializer = extractLazyInitializer( data.getInstance() ); if ( lazyInitializer == null ) { - state = State.INITIALIZED; - concreteDescriptor = session.getEntityPersister( null, instance ); - entityIdentifier = concreteDescriptor.getIdentifier( instance, session ); + data.setState( State.INITIALIZED ); + data.concreteDescriptor = session.getEntityPersister( null, instance ); + data.entityIdentifier = data.concreteDescriptor.getIdentifier( instance, session ); } else if ( lazyInitializer.isUninitialized() ) { - state = eager ? State.RESOLVED : State.INITIALIZED; + data.setState( eager ? State.RESOLVED : State.INITIALIZED ); // Read the discriminator from the result set if necessary final Object discriminatorValue = discriminatorValueAssembler.assemble( rowProcessingState ); - concreteDescriptor = fetchedPart.resolveDiscriminatorValue( discriminatorValue ).getEntityPersister(); - entityIdentifier = lazyInitializer.getIdentifier(); + data.concreteDescriptor = fetchedPart.resolveDiscriminatorValue( discriminatorValue ).getEntityPersister(); + data.entityIdentifier = lazyInitializer.getIdentifier(); } else { - state = State.INITIALIZED; - concreteDescriptor = session.getEntityPersister( null, lazyInitializer.getImplementation() ); - entityIdentifier = lazyInitializer.getIdentifier(); + data.setState( State.INITIALIZED ); + data.concreteDescriptor = session.getEntityPersister( null, lazyInitializer.getImplementation() ); + data.entityIdentifier = lazyInitializer.getIdentifier(); } - entityInstance = instance; - final Initializer initializer = keyValueAssembler.getInitializer(); + data.setInstance( instance ); + final Initializer initializer = keyValueAssembler.getInitializer(); if ( initializer != null ) { - initializer.resolveInstance( entityIdentifier ); + initializer.resolveInstance( data.entityIdentifier, rowProcessingState ); } - else if ( !rowProcessingState.isQueryCacheHit() && rowProcessingState.getQueryOptions().isResultCachingEnabled() == Boolean.TRUE ) { + else if ( rowProcessingState.needsResolveState() ) { // Resolve the state of the identifier if result caching is enabled and this is not a query cache hit discriminatorValueAssembler.resolveState( rowProcessingState ); keyValueAssembler.resolveState( rowProcessingState ); @@ -253,38 +209,38 @@ public class DiscriminatedEntityInitializer extends AbstractInitializer implemen } @Override - public void initializeInstance() { - if ( state != State.RESOLVED ) { + public void initializeInstance(DiscriminatedEntityInitializerData data) { + if ( data.getState() != State.RESOLVED ) { return; } - state = State.INITIALIZED; - entityInstance = rowProcessingState.getSession().internalLoad( - concreteDescriptor.getEntityName(), - entityIdentifier, + data.setState( State.INITIALIZED ); + data.setInstance( data.getRowProcessingState().getSession().internalLoad( + data.concreteDescriptor.getEntityName(), + data.entityIdentifier, eager, // should not be null since we checked already. null would indicate bad data (ala, not-found handling) false - ); + ) ); } @Override - public void initializeInstanceFromParent(Object parentInstance) { + public void initializeInstanceFromParent(Object parentInstance, DiscriminatedEntityInitializerData data) { final AttributeMapping attributeMapping = getInitializedPart().asAttributeMapping(); final Object instance = attributeMapping != null ? attributeMapping.getValue( parentInstance ) : parentInstance; if ( instance == null ) { - state = State.MISSING; - entityInstance = null; - entityIdentifier = null; - concreteDescriptor = null; + data.setState( State.MISSING ); + data.setInstance( null ); + data.entityIdentifier = null; + data.concreteDescriptor = null; } else { - state = State.INITIALIZED; - entityInstance = instance; + data.setState( State.INITIALIZED ); + data.setInstance( instance ); // No need to initialize this - entityIdentifier = null; - concreteDescriptor = null; + data.entityIdentifier = null; + data.concreteDescriptor = null; if ( eager ) { Hibernate.initialize( instance ); } @@ -292,31 +248,31 @@ public class DiscriminatedEntityInitializer extends AbstractInitializer implemen } @Override - protected void forEachSubInitializer(BiConsumer consumer, X arg) { - final Initializer initializer = keyValueAssembler.getInitializer(); + protected void forEachSubInitializer(BiConsumer, RowProcessingState> consumer, InitializerData data) { + final Initializer initializer = keyValueAssembler.getInitializer(); if ( initializer != null ) { - consumer.accept( initializer, arg ); + consumer.accept( initializer, data.getRowProcessingState() ); } } @Override public EntityPersister getEntityDescriptor() { - return concreteDescriptor; + throw new UnsupportedOperationException("Discriminated association has no static entity type"); } @Override - public Object getEntityInstance() { - return entityInstance; + public Object getEntityInstance(DiscriminatedEntityInitializerData data) { + return data.getInstance(); } @Override - public boolean isEntityInitialized() { - return state == State.INITIALIZED; + public EntityPersister getConcreteDescriptor(DiscriminatedEntityInitializerData data) { + return data.concreteDescriptor; } @Override - public EntityPersister getConcreteDescriptor() { - return concreteDescriptor; + public @Nullable Object getEntityIdentifier(DiscriminatedEntityInitializerData data) { + return data.entityIdentifier; } @Override @@ -334,15 +290,4 @@ public class DiscriminatedEntityInitializer extends AbstractInitializer implemen return "DiscriminatedEntityInitializer(" + LoggingHelper.toLoggableString( getNavigablePath() ) + ")"; } - @Override - public EntityKey getEntityKey() { - throw new UnsupportedOperationException( - "This should never happen, because this initializer has not child initializers" ); - } - - @Override - public Object getParentKey() { - throw new UnsupportedOperationException( - "This should never happen, because this initializer has not child initializers" ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/DiscriminatedEntityResult.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/DiscriminatedEntityResult.java index a1bd8bfd62..7b8999058b 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/DiscriminatedEntityResult.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/DiscriminatedEntityResult.java @@ -12,7 +12,6 @@ import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.DomainResultCreationState; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.InitializerProducer; @@ -42,14 +41,7 @@ public class DiscriminatedEntityResult extends AbstractDiscriminatedEntityRes @Override public DomainResultAssembler createResultAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createResultAssembler( (InitializerParent) parentAccess, creationState ); - } - - @Override - public DomainResultAssembler createResultAssembler( - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { //noinspection unchecked return new EntityAssembler( @@ -59,15 +51,15 @@ public class DiscriminatedEntityResult extends AbstractDiscriminatedEntityRes } @Override - public Initializer createInitializer( + public Initializer createInitializer( DiscriminatedEntityResult resultGraphNode, - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return resultGraphNode.createInitializer( parent, creationState ); } @Override - public Initializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { + public Initializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { return new DiscriminatedEntityInitializer( parent, getReferencedMappingType(), diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityAssembler.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityAssembler.java index 50c13c477c..445fbdcc1c 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityAssembler.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityAssembler.java @@ -9,8 +9,8 @@ package org.hibernate.sql.results.graph.entity.internal; import java.util.function.BiConsumer; import org.hibernate.sql.results.graph.DomainResultAssembler; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.entity.EntityInitializer; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.descriptor.java.JavaType; @@ -19,13 +19,11 @@ import org.hibernate.type.descriptor.java.JavaType; */ public class EntityAssembler implements DomainResultAssembler { private final JavaType javaType; - private final EntityInitializer initializer; + private final EntityInitializer initializer; - public EntityAssembler( - JavaType javaType, - EntityInitializer initializer) { + public EntityAssembler(JavaType javaType, EntityInitializer initializer) { this.javaType = javaType; - this.initializer = initializer; + this.initializer = (EntityInitializer) initializer; } @Override @@ -34,16 +32,17 @@ public class EntityAssembler implements DomainResultAssembler { } @Override - public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) { + public Object assemble(RowProcessingState rowProcessingState) { // Ensure that the instance really is initialized // This is important for key-many-to-ones that are part of a collection key fk, // as the instance is needed for resolveKey before initializing the instance in RowReader - initializer.resolveInstance(); - return initializer.getEntityInstance(); + final InitializerData data = initializer.getData( rowProcessingState ); + initializer.resolveInstance( data ); + return initializer.getEntityInstance( data ); } @Override - public EntityInitializer getInitializer() { + public EntityInitializer getInitializer() { return initializer; } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchImpl.java index 1f9f151541..a051ef92b6 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchImpl.java @@ -14,7 +14,6 @@ import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.FetchParent; import org.hibernate.sql.results.graph.InitializerParent; -import org.hibernate.sql.results.graph.basic.BasicResultAssembler; import org.hibernate.sql.results.graph.entity.EntityInitializer; /** @@ -46,16 +45,15 @@ public class EntityDelayedFetchImpl extends AbstractNonJoinedEntityFetch { } @Override - public EntityInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { + public EntityInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { return new EntityDelayedFetchInitializer( parent, getNavigablePath(), getEntityValuedModelPart(), isSelectByUniqueKey(), - getKeyResult().createResultAssembler( parent, creationState ), - getDiscriminatorFetch() != null - ? (BasicResultAssembler) getDiscriminatorFetch().createResultAssembler( parent, creationState ) - : null + getKeyResult(), + getDiscriminatorFetch(), + creationState ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java index 8fe889c684..ea7252357a 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java @@ -22,13 +22,17 @@ import org.hibernate.persister.entity.EntityPersister; import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.LazyInitializer; import org.hibernate.spi.NavigablePath; +import org.hibernate.sql.results.graph.AssemblerCreationState; +import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Initializer; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.InitializerParent; +import org.hibernate.sql.results.graph.basic.BasicFetch; import org.hibernate.sql.results.graph.basic.BasicResultAssembler; import org.hibernate.sql.results.graph.entity.EntityInitializer; import org.hibernate.sql.results.graph.internal.AbstractInitializer; +import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.Type; import org.checkerframework.checker.nullness.qual.Nullable; @@ -39,48 +43,36 @@ import static org.hibernate.sql.results.graph.entity.internal.EntityInitializerI * @author Andrea Boriero * @author Steve Ebersole */ -public class EntityDelayedFetchInitializer extends AbstractInitializer implements EntityInitializer { +public class EntityDelayedFetchInitializer + extends AbstractInitializer + implements EntityInitializer { - private final InitializerParent parent; + private final InitializerParent parent; private final NavigablePath navigablePath; private final boolean isPartOfKey; private final ToOneAttributeMapping referencedModelPart; private final boolean selectByUniqueKey; private final DomainResultAssembler identifierAssembler; - private final BasicResultAssembler discriminatorAssembler; + private final @Nullable BasicResultAssembler discriminatorAssembler; - // per-row state - private Object entityInstance; - private Object identifier; + public static class EntityDelayedFetchInitializerData extends InitializerData { + // per-row state + protected @Nullable Object entityIdentifier; - /** - * @deprecated Use {@link #EntityDelayedFetchInitializer(InitializerParent, NavigablePath, ToOneAttributeMapping, boolean, DomainResultAssembler, BasicResultAssembler)} instead. - */ - @Deprecated(forRemoval = true) - public EntityDelayedFetchInitializer( - FetchParentAccess parentAccess, - NavigablePath fetchedNavigable, - ToOneAttributeMapping referencedModelPart, - boolean selectByUniqueKey, - DomainResultAssembler identifierAssembler, - BasicResultAssembler discriminatorAssembler) { - this( - (InitializerParent) parentAccess, - fetchedNavigable, - referencedModelPart, - selectByUniqueKey, - identifierAssembler, - discriminatorAssembler - ); + public EntityDelayedFetchInitializerData(RowProcessingState rowProcessingState) { + super( rowProcessingState ); + } } public EntityDelayedFetchInitializer( - InitializerParent parent, + InitializerParent parent, NavigablePath fetchedNavigable, ToOneAttributeMapping referencedModelPart, boolean selectByUniqueKey, - DomainResultAssembler identifierAssembler, - BasicResultAssembler discriminatorAssembler) { + DomainResult keyResult, + @Nullable BasicFetch discriminatorResult, + AssemblerCreationState creationState) { + super( creationState ); // associations marked with `@NotFound` are ALWAYS eagerly fetched, unless we're resolving the concrete type assert !referencedModelPart.hasNotFoundAction() || referencedModelPart.getEntityMappingType().isConcreteProxy(); @@ -89,8 +81,15 @@ public class EntityDelayedFetchInitializer extends AbstractInitializer implement this.isPartOfKey = Initializer.isPartOfKey( fetchedNavigable, parent ); this.referencedModelPart = referencedModelPart; this.selectByUniqueKey = selectByUniqueKey; - this.identifierAssembler = identifierAssembler; - this.discriminatorAssembler = discriminatorAssembler; + this.identifierAssembler = keyResult.createResultAssembler( this, creationState ); + this.discriminatorAssembler = discriminatorResult == null + ? null + : (BasicResultAssembler) discriminatorResult.createResultAssembler( this, creationState ); + } + + @Override + protected InitializerData createInitializerData(RowProcessingState rowProcessingState) { + return new EntityDelayedFetchInitializerData( rowProcessingState ); } @Override @@ -104,18 +103,19 @@ public class EntityDelayedFetchInitializer extends AbstractInitializer implement } @Override - public void resolveInstance() { - if ( state != State.KEY_RESOLVED ) { + public void resolveInstance(EntityDelayedFetchInitializerData data) { + if ( data.getState() != State.KEY_RESOLVED ) { return; } - state = State.RESOLVED; + data.setState( State.RESOLVED ); - identifier = identifierAssembler.assemble( rowProcessingState ); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + data.entityIdentifier = identifierAssembler.assemble( rowProcessingState ); - if ( identifier == null ) { - entityInstance = null; - state = State.MISSING; + if ( data.entityIdentifier == null ) { + data.setInstance( null ); + data.setState( State.MISSING ); } else { final SharedSessionContractImplementor session = rowProcessingState.getSession(); @@ -131,10 +131,10 @@ public class EntityDelayedFetchInitializer extends AbstractInitializer implement if ( concreteDescriptor == null ) { // If we find no discriminator it means there's no entity in the target table if ( !referencedModelPart.isOptional() ) { - throw new FetchNotFoundException( entityPersister.getEntityName(), identifier ); + throw new FetchNotFoundException( entityPersister.getEntityName(), data.entityIdentifier ); } - entityInstance = null; - state = State.MISSING; + data.setInstance( null ); + data.setState( State.MISSING ); return; } } @@ -156,55 +156,55 @@ public class EntityDelayedFetchInitializer extends AbstractInitializer implement final EntityUniqueKey euk = new EntityUniqueKey( concreteDescriptor.getEntityName(), uniqueKeyPropertyName, - identifier, + data.entityIdentifier, uniqueKeyPropertyType, session.getFactory() ); - entityInstance = persistenceContext.getEntity( euk ); - if ( entityInstance == null ) { + data.setInstance( persistenceContext.getEntity( euk ) ); + if ( data.getInstance() == null ) { // For unique-key mappings, we always use bytecode-laziness if possible, // because we can't generate a proxy based on the unique key yet if ( referencedModelPart.isLazy() ) { - entityInstance = LazyPropertyInitializer.UNFETCHED_PROPERTY; + data.setInstance( LazyPropertyInitializer.UNFETCHED_PROPERTY ); } else { - entityInstance = concreteDescriptor.loadByUniqueKey( + data.setInstance( concreteDescriptor.loadByUniqueKey( uniqueKeyPropertyName, - identifier, + data.entityIdentifier, session - ); + ) ); // If the entity was not in the Persistence Context, but was found now, // add it to the Persistence Context - if ( entityInstance != null ) { - persistenceContext.addEntity( euk, entityInstance ); + if ( data.getInstance() != null ) { + persistenceContext.addEntity( euk, data.getInstance() ); } } } - if ( entityInstance != null ) { - entityInstance = persistenceContext.proxyFor( entityInstance ); + if ( data.getInstance() != null ) { + data.setInstance( persistenceContext.proxyFor( data.getInstance() ) ); } } else { - final EntityKey entityKey = new EntityKey( identifier, concreteDescriptor ); + final EntityKey entityKey = new EntityKey( data.entityIdentifier, concreteDescriptor ); final EntityHolder holder = persistenceContext.getEntityHolder( entityKey ); if ( holder != null && holder.getEntity() != null ) { - entityInstance = persistenceContext.proxyFor( holder, concreteDescriptor ); + data.setInstance( persistenceContext.proxyFor( holder, concreteDescriptor ) ); } // For primary key based mappings we only use bytecode-laziness if the attribute is optional, // because the non-optionality implies that it is safe to have a proxy else if ( referencedModelPart.isOptional() && referencedModelPart.isLazy() ) { - entityInstance = LazyPropertyInitializer.UNFETCHED_PROPERTY; + data.setInstance( LazyPropertyInitializer.UNFETCHED_PROPERTY ); } else { - entityInstance = session.internalLoad( + data.setInstance( session.internalLoad( concreteDescriptor.getEntityName(), - identifier, + data.entityIdentifier, false, false - ); + ) ); - final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entityInstance ); + final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( data.getInstance() ); if ( lazyInitializer != null ) { lazyInitializer.setUnwrap( referencedModelPart.isUnwrapProxy() && concreteDescriptor.isInstrumented() ); } @@ -214,23 +214,24 @@ public class EntityDelayedFetchInitializer extends AbstractInitializer implement } @Override - public void resolveInstance(Object instance) { + public void resolveInstance(Object instance, EntityDelayedFetchInitializerData data) { if ( instance == null ) { - state = State.MISSING; - identifier = null; - entityInstance = null; + data.setState( State.MISSING ); + data.entityIdentifier = null; + data.setInstance( null ); } else { - state = State.RESOLVED; + data.setState( State.RESOLVED ); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); final SharedSessionContractImplementor session = rowProcessingState.getSession(); final EntityPersister concreteDescriptor = referencedModelPart.getEntityMappingType().getEntityPersister(); - identifier = concreteDescriptor.getIdentifier( instance, session ); - entityInstance = instance; - final Initializer initializer = identifierAssembler.getInitializer(); + data.entityIdentifier = concreteDescriptor.getIdentifier( instance, session ); + data.setInstance( instance ); + final Initializer initializer = identifierAssembler.getInitializer(); if ( initializer != null ) { - initializer.resolveInstance( identifier ); + initializer.resolveInstance( data.entityIdentifier, rowProcessingState ); } - else if ( !rowProcessingState.isQueryCacheHit() && rowProcessingState.getQueryOptions().isResultCachingEnabled() == Boolean.TRUE ) { + else if ( rowProcessingState.needsResolveState() ) { // Resolve the state of the identifier if result caching is enabled and this is not a query cache hit identifierAssembler.resolveState( rowProcessingState ); } @@ -238,10 +239,10 @@ public class EntityDelayedFetchInitializer extends AbstractInitializer implement } @Override - protected void forEachSubInitializer(BiConsumer consumer, X arg) { - final Initializer initializer = identifierAssembler.getInitializer(); + protected void forEachSubInitializer(BiConsumer, RowProcessingState> consumer, InitializerData data) { + final Initializer initializer = identifierAssembler.getInitializer(); if ( initializer != null ) { - consumer.accept( initializer, arg ); + consumer.accept( initializer, data.getRowProcessingState() ); } } @@ -251,22 +252,12 @@ public class EntityDelayedFetchInitializer extends AbstractInitializer implement } @Override - public Object getEntityInstance() { - return entityInstance; + public Object getEntityInstance(EntityDelayedFetchInitializerData data) { + return data.getInstance(); } @Override - public boolean isEntityInitialized() { - return false; - } - - @Override - public FetchParentAccess getFetchParentAccess() { - return (FetchParentAccess) parent; - } - - @Override - public @Nullable InitializerParent getParent() { + public @Nullable InitializerParent getParent() { return parent; } @@ -281,10 +272,15 @@ public class EntityDelayedFetchInitializer extends AbstractInitializer implement } @Override - public EntityPersister getConcreteDescriptor() { + public EntityPersister getConcreteDescriptor(EntityDelayedFetchInitializerData data) { return getEntityDescriptor(); } + @Override + public @Nullable Object getEntityIdentifier(EntityDelayedFetchInitializerData data) { + return data.entityIdentifier; + } + @Override public String toString() { return "EntityDelayedFetchInitializer(" + LoggingHelper.toLoggableString( navigablePath ) + ")"; @@ -293,17 +289,6 @@ public class EntityDelayedFetchInitializer extends AbstractInitializer implement //######################### // For Hibernate Reactive //######################### - protected void setEntityInstance(Object entityInstance) { - this.entityInstance = entityInstance; - } - - protected Object getIdentifier() { - return identifier; - } - - protected void setIdentifier(Object identifier) { - this.identifier = identifier; - } protected boolean isSelectByUniqueKey() { return selectByUniqueKey; @@ -313,15 +298,4 @@ public class EntityDelayedFetchInitializer extends AbstractInitializer implement return identifierAssembler; } - @Override - public EntityKey getEntityKey() { - throw new UnsupportedOperationException( - "This should never happen, because this initializer has not child initializers" ); - } - - @Override - public Object getParentKey() { - throw new UnsupportedOperationException( - "This should never happen, because this initializer has not child initializers" ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityFetchJoinedImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityFetchJoinedImpl.java index 71c4f9ead3..25907625b6 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityFetchJoinedImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityFetchJoinedImpl.java @@ -20,7 +20,6 @@ import org.hibernate.sql.results.graph.DomainResultAssembler; 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.FetchParentAccess; import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.InitializerParent; @@ -127,35 +126,28 @@ public class EntityFetchJoinedImpl implements EntityFetch, FetchParent, Initiali @Override public DomainResultAssembler createAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createAssembler( (InitializerParent) parentAccess, creationState ); - } - - @Override - public DomainResultAssembler createAssembler( - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return buildEntityAssembler( creationState.resolveInitializer( this, parent, this ).asEntityInitializer() ); } - protected EntityAssembler buildEntityAssembler(EntityInitializer entityInitializer) { + protected EntityAssembler buildEntityAssembler(EntityInitializer entityInitializer) { return new EntityAssembler( getFetchedMapping().getJavaType(), entityInitializer ); } @Override - public Initializer createInitializer( + public Initializer createInitializer( EntityFetchJoinedImpl resultGraphNode, - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return resultGraphNode.createInitializer( parent, creationState ); } @Override - public EntityInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { + public EntityInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { return new EntityInitializerImpl( this, - creationState.determineEffectiveLockMode( sourceAlias ), + sourceAlias, entityResult.getIdentifierFetch(), entityResult.getDiscriminatorFetch(), keyResult, @@ -165,31 +157,6 @@ public class EntityFetchJoinedImpl implements EntityFetch, FetchParent, Initiali false, creationState ); -// return new EntityJoinedFetchInitializer( -// entityResult, -// getReferencedModePart(), -// getNavigablePath(), -// creationState.determineEffectiveLockMode( sourceAlias ), -// notFoundAction, -// keyResult, -// entityResult.getRowIdResult(), -// entityResult.getIdentifierFetch(), -// entityResult.getDiscriminatorFetch(), -// parentAccess, -// creationState -// ); -// return new EntityInitializerImpl( -// this, -// creationState.determineEffectiveLockMode( sourceAlias ), -// entityResult.getIdentifierFetch(), -// entityResult.getDiscriminatorFetch(), -// keyResult, -// entityResult.getRowIdResult(), -// notFoundAction, -// parentAccess, -// false, -// creationState -// ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityFetchSelectImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityFetchSelectImpl.java index 3d773879a1..34ea79b932 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityFetchSelectImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityFetchSelectImpl.java @@ -53,7 +53,7 @@ public class EntityFetchSelectImpl extends AbstractNonJoinedEntityFetch { } @Override - public EntityInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { + public EntityInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { return EntitySelectFetchInitializerBuilder.createInitializer( parent, getFetchedMapping(), diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityInitializerImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityInitializerImpl.java index bef21be1bf..d1348994dc 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityInitializerImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityInitializerImpl.java @@ -6,7 +6,6 @@ */ package org.hibernate.sql.results.graph.entity.internal; -import java.util.ArrayList; import java.util.Collection; import java.util.function.BiConsumer; @@ -36,7 +35,6 @@ import org.hibernate.event.spi.HibernateMonitoringEvent; import org.hibernate.event.spi.PreLoadEvent; import org.hibernate.event.spi.PreLoadEventListener; import org.hibernate.internal.log.LoggingHelper; -import org.hibernate.internal.util.StringHelper; import org.hibernate.loader.ast.internal.CacheEntityLoaderHelper; import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMetadata; @@ -60,12 +58,11 @@ import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Fetch; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Initializer; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.basic.BasicResultAssembler; import org.hibernate.sql.results.graph.entity.EntityInitializer; -import org.hibernate.sql.results.graph.entity.EntityLoadingLogging; import org.hibernate.sql.results.graph.entity.EntityResultGraphNode; import org.hibernate.sql.results.graph.internal.AbstractInitializer; import org.hibernate.sql.results.internal.NullValueAssembler; @@ -86,7 +83,8 @@ import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer; /** * @author Andrea Boriero */ -public class EntityInitializerImpl extends AbstractInitializer implements EntityInitializer { +public class EntityInitializerImpl extends AbstractInitializer + implements EntityInitializer { // NOTE : even though we only keep the EntityDescriptor here, rather than EntityResultGraphNode // the "scope" of this initializer is a specific EntityReference. @@ -99,8 +97,8 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity private final EntityPersister entityDescriptor; private final EntityPersister rootEntityDescriptor; private final NavigablePath navigablePath; - private final LockMode lockMode; - private final @Nullable InitializerParent parent; + private final String sourceAlias; + private final @Nullable InitializerParent parent; private final NotFoundAction notFoundAction; private final boolean isPartOfKey; private final boolean isResultInitializer; @@ -113,28 +111,40 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity private final @Nullable DomainResultAssembler rowIdAssembler; private final DomainResultAssembler[][] assemblers; - private final Initializer[][] subInitializers; + private final Initializer[][] subInitializers; - private boolean shallowCached; + public static class EntityInitializerData extends InitializerData { - // per-row state - private @Nullable EntityPersister concreteDescriptor; - private @Nullable EntityKey entityKey; - private @Nullable Object entityInstance; - private @Nullable Object entityInstanceForNotify; - private @Nullable EntityHolder entityHolder; + protected boolean shallowCached; + protected LockMode lockMode; + protected String uniqueKeyAttributePath; + protected Type[] uniqueKeyPropertyTypes; + protected boolean canUseEmbeddedIdentifierInstanceAsEntity; + protected boolean hasCallbackActions; + + // per-row state + protected @Nullable EntityPersister concreteDescriptor; + protected @Nullable EntityKey entityKey; + protected @Nullable Object entityInstanceForNotify; + protected @Nullable EntityHolder entityHolder; + + public EntityInitializerData(RowProcessingState rowProcessingState) { + super( rowProcessingState ); + } + } public EntityInitializerImpl( EntityResultGraphNode resultDescriptor, - LockMode lockMode, + String sourceAlias, @Nullable Fetch identifierFetch, @Nullable Fetch discriminatorFetch, @Nullable DomainResult keyResult, @Nullable DomainResult rowIdResult, NotFoundAction notFoundAction, - @Nullable InitializerParent parent, + @Nullable InitializerParent parent, boolean isResultInitializer, AssemblerCreationState creationState) { + super( creationState ); referencedModelPart = resultDescriptor.getEntityValuedModelPart(); entityDescriptor = (EntityPersister) referencedModelPart.getEntityMappingType(); @@ -145,9 +155,8 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity : entityDescriptor.getRootEntityDescriptor().getEntityPersister(); this.navigablePath = resultDescriptor.getNavigablePath(); - this.lockMode = lockMode; + this.sourceAlias = sourceAlias; this.parent = parent; - assert lockMode != null; this.isResultInitializer = isResultInitializer; this.isPartOfKey = Initializer.isPartOfKey( navigablePath, parent ); @@ -157,8 +166,8 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity hasKeyManyToOne = false; } else { - identifierAssembler = identifierFetch.createAssembler( (InitializerParent) this, creationState ); - final Initializer initializer = identifierAssembler.getInitializer(); + identifierAssembler = identifierFetch.createAssembler( this, creationState ); + final Initializer initializer = identifierAssembler.getInitializer(); // For now, assume key many to ones if the identifier has an initializer // todo: improve this hasKeyManyToOne = initializer != null; @@ -166,7 +175,7 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity assert entityDescriptor.hasSubclasses() == (discriminatorFetch != null) : "Discriminator should only be fetched if the entity has subclasses"; discriminatorAssembler = discriminatorFetch != null - ? (BasicResultAssembler) discriminatorFetch.createAssembler( (InitializerParent) this, creationState ) + ? (BasicResultAssembler) discriminatorFetch.createAssembler( this, creationState ) : null; final EntityVersionMapping versionMapping = entityDescriptor.getVersionMapping(); @@ -174,19 +183,19 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity final Fetch versionFetch = resultDescriptor.findFetch( versionMapping ); // If there is a version mapping, there must be a fetch for it assert versionFetch != null; - versionAssembler = versionFetch.createAssembler( (InitializerParent) this, creationState ); + versionAssembler = versionFetch.createAssembler( this, creationState ); } else { versionAssembler = null; } rowIdAssembler = rowIdResult != null - ? rowIdResult.createResultAssembler( (InitializerParent) this, creationState ) + ? rowIdResult.createResultAssembler( this, creationState ) : null; final Collection subMappingTypes = rootEntityDescriptor.getSubMappingTypes(); final DomainResultAssembler[][] assemblers = new DomainResultAssembler[subMappingTypes.size() + 1][]; - final ArrayList[] subInitializers = new ArrayList[subMappingTypes.size() + 1]; + final Initializer[][] subInitializers = new Initializer[subMappingTypes.size() + 1][]; assemblers[rootEntityDescriptor.getSubclassId()] = new DomainResultAssembler[rootEntityDescriptor.getNumberOfFetchables()]; for ( EntityMappingType subMappingType : subMappingTypes ) { @@ -199,18 +208,18 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity final Fetch fetch = resultDescriptor.findFetch( attributeMapping ); final DomainResultAssembler stateAssembler = fetch == null ? new NullValueAssembler<>( attributeMapping.getMappedType().getMappedJavaType() ) - : fetch.createAssembler( (InitializerParent) this, creationState ); + : fetch.createAssembler( this, creationState ); final int stateArrayPosition = attributeMapping.getStateArrayPosition(); final EntityMappingType declaringType = attributeMapping.getDeclaringType().asEntityMappingType(); final int subclassId = declaringType.getSubclassId(); - final Initializer subInitializer = stateAssembler.getInitializer(); + final Initializer subInitializer = stateAssembler.getInitializer(); if ( subInitializer != null ) { if ( subInitializers[subclassId] == null ) { - subInitializers[subclassId] = new ArrayList<>(); + subInitializers[subclassId] = new Initializer[size]; } - subInitializers[subclassId].add( subInitializer ); + subInitializers[subclassId][stateArrayPosition] = subInitializer; } assemblers[subclassId][stateArrayPosition] = stateAssembler; @@ -218,99 +227,106 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity assemblers[subMappingType.getSubclassId()][stateArrayPosition] = stateAssembler; if ( subInitializer != null ) { if ( subInitializers[subMappingType.getSubclassId()] == null ) { - subInitializers[subMappingType.getSubclassId()] = new ArrayList<>(); + subInitializers[subMappingType.getSubclassId()] = new Initializer[size]; } - subInitializers[subMappingType.getSubclassId()].add( subInitializer ); + subInitializers[subMappingType.getSubclassId()][stateArrayPosition] = subInitializer; } } } - final Initializer[][] subInitializersArray = new Initializer[subInitializers.length][]; - for ( int i = 0; i < subInitializers.length; i++ ) { - final ArrayList subInitializerList = subInitializers[i]; - if ( subInitializerList == null || subInitializerList.isEmpty() ) { - subInitializersArray[i] = Initializer.EMPTY_ARRAY; - } - else { - subInitializersArray[i] = subInitializerList.toArray( Initializer.EMPTY_ARRAY ); + OUTER: for ( int i = 0; i < subInitializers.length; i++ ) { + if ( subInitializers[i] != null ) { + for ( Initializer initializer : subInitializers[i] ) { + if ( initializer != null ) { + continue OUTER; + } + } } + subInitializers[i] = Initializer.EMPTY_ARRAY; } + this.assemblers = assemblers; - this.subInitializers = subInitializersArray; + this.subInitializers = subInitializers; this.notFoundAction = notFoundAction; - this.keyAssembler = keyResult == null ? null : keyResult.createResultAssembler( (InitializerParent) this, creationState ); + this.keyAssembler = keyResult == null ? null : keyResult.createResultAssembler( this, creationState ); } @Override - public void resolveKey() { - resolveKey( rowProcessingState, false ); + protected EntityInitializerData createInitializerData(RowProcessingState rowProcessingState) { + return new EntityInitializerData( rowProcessingState ); + } + + @Override + public void resolveKey(EntityInitializerData data) { + resolveKey( data, false ); + } + + @Override + public @Nullable Object getEntityIdentifier(EntityInitializerData data) { + return data.entityKey == null ? null : data.entityKey.getIdentifier(); } @Override public @Nullable EntityKey resolveEntityKeyOnly(RowProcessingState rowProcessingState) { - resolveKey( rowProcessingState, true ); - if ( state == State.MISSING ) { + final EntityInitializerData data = getData( rowProcessingState ); + resolveKey( data, true ); + if ( data.getState() == State.MISSING ) { return null; } - if ( entityKey == null ) { + if ( data.entityKey == null ) { assert identifierAssembler != null; final Object id = identifierAssembler.assemble( rowProcessingState ); if ( id == null ) { - setMissing( rowProcessingState ); + setMissing( data ); return null; } - resolveEntityKey( rowProcessingState, id ); + resolveEntityKey( data, id ); } - return entityKey; + return data.entityKey; } - public void resolveKey(RowProcessingState rowProcessingState, boolean entityKeyOnly) { + protected void resolveKey(EntityInitializerData data, boolean entityKeyOnly) { // todo (6.0) : atm we do not handle sequential selects // - see AbstractEntityPersister#hasSequentialSelect and // AbstractEntityPersister#getSequentialSelect in 5.2 - if ( state != State.UNINITIALIZED ) { + if ( data.getState() != State.UNINITIALIZED ) { return; } - state = State.KEY_RESOLVED; + data.setState( State.KEY_RESOLVED ); // reset row state - concreteDescriptor = null; - entityKey = null; - entityInstance = null; - entityInstanceForNotify = null; - entityHolder = null; - - if ( EntityLoadingLogging.ENTITY_LOADING_LOGGER.isTraceEnabled() ) { - EntityLoadingLogging.ENTITY_LOADING_LOGGER.tracef( - "(%s) Beginning Initializer#resolveKey process for entity : %s", - StringHelper.collapse( this.getClass().getName() ), - getNavigablePath() - ); - } + data.concreteDescriptor = null; + data.entityKey = null; + data.setInstance( null ); + data.entityInstanceForNotify = null; + data.entityHolder = null; + final RowProcessingState rowProcessingState = data.getRowProcessingState(); final Object id; if ( identifierAssembler == null ) { id = rowProcessingState.getEntityId(); assert id != null : "Initializer requires a not null id for loading"; } else { - final Initializer initializer = identifierAssembler.getInitializer(); + //noinspection unchecked + final Initializer initializer = (Initializer) identifierAssembler.getInitializer(); if ( initializer != null ) { - initializer.resolveKey(); - if ( initializer.getState() == State.MISSING ) { - setMissing( rowProcessingState ); + final InitializerData subData = initializer.getData( rowProcessingState ); + initializer.resolveKey( subData ); + if ( subData.getState() == State.MISSING ) { + setMissing( data ); return; } else { - concreteDescriptor = determineConcreteEntityDescriptor( + data.concreteDescriptor = determineConcreteEntityDescriptor( rowProcessingState, discriminatorAssembler, entityDescriptor ); - assert concreteDescriptor != null; + assert data.concreteDescriptor != null; if ( hasKeyManyToOne ) { - if ( !shallowCached && !entityKeyOnly ) { - resolveKeySubInitializers( rowProcessingState ); + if ( !data.shallowCached && !entityKeyOnly ) { + resolveKeySubInitializers( data ); } return; } @@ -318,21 +334,21 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity } id = identifierAssembler.assemble( rowProcessingState ); if ( id == null ) { - setMissing( rowProcessingState ); + setMissing( data ); return; } } - resolveEntityKey( rowProcessingState, id ); + resolveEntityKey( data, id ); if ( !entityKeyOnly ) { // Resolve the entity instance early as we have no key many-to-one - resolveInstance(); - if ( !shallowCached ) { - if ( state == State.INITIALIZED ) { - if ( entityHolder.getEntityInitializer() == null ) { + resolveInstance( data ); + if ( !data.shallowCached ) { + if ( data.getState() == State.INITIALIZED ) { + if ( data.entityHolder.getEntityInitializer() == null ) { // The entity is already part of the persistence context, // so let's figure out the loaded state and only run sub-initializers if necessary - resolveInstanceSubInitializers( rowProcessingState ); + resolveInstanceSubInitializers( data ); } // If the entity is initialized and getEntityInitializer() == this, // we already processed a row for this entity before, @@ -340,29 +356,31 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity // because a row might contain data that sub-initializers want to consume else { // todo: try to diff the eagerness of the sub-initializers to avoid further processing - resolveKeySubInitializers( rowProcessingState ); + resolveKeySubInitializers( data ); } } else { - resolveKeySubInitializers( rowProcessingState ); + resolveKeySubInitializers( data ); } } } } - protected void resolveInstanceSubInitializers(RowProcessingState rowProcessingState) { - final Initializer[] initializers = subInitializers[concreteDescriptor.getSubclassId()]; + protected void resolveInstanceSubInitializers(EntityInitializerData data) { + final Initializer[] initializers = subInitializers[data.concreteDescriptor.getSubclassId()]; if ( initializers.length == 0 ) { return; } - final EntityEntry entityEntry = rowProcessingState.getSession() + final EntityEntry entityEntry = data.entityHolder.getEntityEntry(); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + assert entityEntry == rowProcessingState.getSession() .getPersistenceContextInternal() - .getEntry( entityInstanceForNotify ); + .getEntry( data.entityInstanceForNotify ); final Object[] loadedState = entityEntry.getLoadedState(); final Object[] state; if ( loadedState == null ) { if ( entityEntry.getStatus() == Status.READ_ONLY ) { - state = concreteDescriptor.getValues( entityInstanceForNotify ); + state = data.concreteDescriptor.getValues( data.entityInstanceForNotify ); } else { // This branch is entered when a load happens while a cache entry is assembling. @@ -375,60 +393,57 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity else { state = loadedState; } - for ( Initializer initializer : initializers ) { - final AttributeMapping attribute = initializer.getInitializedPart().asAttributeMapping(); - final Object subInstance = state[attribute.getStateArrayPosition()]; - if ( subInstance == LazyPropertyInitializer.UNFETCHED_PROPERTY ) { - // Go through the normal initializer process - initializer.resolveKey(); - } - else { - initializer.resolveInstance( subInstance ); + for ( int i = 0; i < initializers.length; i++ ) { + final Initializer initializer = initializers[i]; + if ( initializer != null ) { + final Object subInstance = state[i]; + if ( subInstance == UNFETCHED_PROPERTY ) { + // Go through the normal initializer process + initializer.resolveKey( rowProcessingState ); + } + else { + initializer.resolveInstance( subInstance, rowProcessingState ); + } } } } - private void resolveKeySubInitializers(RowProcessingState rowProcessingState) { - for ( Initializer initializer : subInitializers[concreteDescriptor.getSubclassId()] ) { - initializer.resolveKey(); + private void resolveKeySubInitializers(EntityInitializerData data) { + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + for ( Initializer initializer : subInitializers[data.concreteDescriptor.getSubclassId()] ) { + if ( initializer != null ) { + initializer.resolveKey( rowProcessingState ); + } } } @EnsuresNonNull( "entityKey" ) - protected void resolveEntityKey(RowProcessingState rowProcessingState, Object id) { - if ( concreteDescriptor == null ) { - concreteDescriptor = determineConcreteEntityDescriptor( - rowProcessingState, + protected void resolveEntityKey(EntityInitializerData data, Object id) { + if ( data.concreteDescriptor == null ) { + data.concreteDescriptor = determineConcreteEntityDescriptor( + data.getRowProcessingState(), discriminatorAssembler, entityDescriptor ); - assert concreteDescriptor != null; - } - entityKey = new EntityKey( id, concreteDescriptor ); - if ( EntityLoadingLogging.ENTITY_LOADING_LOGGER.isDebugEnabled() ) { - EntityLoadingLogging.ENTITY_LOADING_LOGGER.debugf( - "(%s) Hydrated EntityKey (%s): %s", - getSimpleConcreteImplName(), - getNavigablePath(), - entityKey.getIdentifier() - ); + assert data.concreteDescriptor != null; } + data.entityKey = new EntityKey( id, data.concreteDescriptor ); } - protected void setMissing(RowProcessingState rowProcessingState) { - entityKey = null; - concreteDescriptor = null; - entityInstance = null; - entityInstanceForNotify = null; - entityHolder = null; - state = State.MISSING; + protected void setMissing(EntityInitializerData data) { + data.entityKey = null; + data.concreteDescriptor = null; + data.setInstance( null ); + data.entityInstanceForNotify = null; + data.entityHolder = null; + data.setState( State.MISSING ); // super processes the foreign-key target column. here we // need to also look at the foreign-key value column to check // for a dangling foreign-key if ( keyAssembler != null ) { - final Object fkKeyValue = keyAssembler.assemble( rowProcessingState ); + final Object fkKeyValue = keyAssembler.assemble( data.getRowProcessingState() ); if ( fkKeyValue != null ) { if ( notFoundAction != NotFoundAction.IGNORE ) { throw new FetchNotFoundException( @@ -436,37 +451,31 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity fkKeyValue ); } - else { - EntityLoadingLogging.ENTITY_LOADING_LOGGER.debugf( - "Ignoring dangling foreign-key due to `@NotFound(IGNORE); association will be null - %s", - getNavigablePath() - ); - } } } } @Override - public void initializeInstanceFromParent(Object parentInstance) { + public void initializeInstanceFromParent(Object parentInstance, EntityInitializerData data) { final AttributeMapping attributeMapping = getInitializedPart().asAttributeMapping(); final Object instance = attributeMapping != null ? attributeMapping.getValue( parentInstance ) : parentInstance; - final SharedSessionContractImplementor session = rowProcessingState.getSession(); + final SharedSessionContractImplementor session = data.getRowProcessingState().getSession(); if ( instance == null ) { - setMissing( rowProcessingState ); + setMissing( data ); } else { - entityInstance = instance; - entityInstanceForNotify = Hibernate.unproxy( instance ); - concreteDescriptor = session.getEntityPersister( null, entityInstanceForNotify ); + data.setInstance( instance ); + data.entityInstanceForNotify = Hibernate.unproxy( instance ); + data.concreteDescriptor = session.getEntityPersister( null, data.entityInstanceForNotify ); resolveEntityKey( - rowProcessingState, - concreteDescriptor.getIdentifier( entityInstanceForNotify, session ) + data, + data.concreteDescriptor.getIdentifier( data.entityInstanceForNotify, session ) ); - entityHolder = session.getPersistenceContextInternal().getEntityHolder( entityKey ); - state = State.INITIALIZED; - initializeSubInstancesFromParent( rowProcessingState ); + data.entityHolder = session.getPersistenceContextInternal().getEntityHolder( data.entityKey ); + data.setState( State.INITIALIZED ); + initializeSubInstancesFromParent( data ); } } @@ -519,40 +528,67 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity } @Override - public @Nullable EntityKey getEntityKey() { - return entityKey; + public Object getEntityInstance(EntityInitializerData data) { + return data.getInstance(); } @Override - public Object getEntityInstance() { - return entityInstance; - } - - protected void setEntityInstance(Object entityInstance) { - this.entityInstance = entityInstance; + public Object getTargetInstance(EntityInitializerData data) { + return data.entityInstanceForNotify; } @Override - public Object getTargetInstance() { - return entityInstanceForNotify; - } - - @Override - public FetchParentAccess getFetchParentAccess() { - return (FetchParentAccess) parent; - } - - @Override - public @Nullable InitializerParent getParent() { + public @Nullable InitializerParent getParent() { return parent; } @Override public void startLoading(RowProcessingState rowProcessingState) { + final EntityInitializerData data = createInitializerData( rowProcessingState ); + rowProcessingState.setInitializerData( initializerId, data ); if ( rowProcessingState.isQueryCacheHit() && entityDescriptor.useShallowQueryCacheLayout() ) { - shallowCached = true; + data.shallowCached = true; + } + data.lockMode = rowProcessingState.determineEffectiveLockMode( sourceAlias ); + if ( isResultInitializer() ) { + data.uniqueKeyAttributePath = rowProcessingState.getEntityUniqueKeyAttributePath(); + if ( data.uniqueKeyAttributePath != null ) { + data.uniqueKeyPropertyTypes = getParentEntityAttributeTypes( data.uniqueKeyAttributePath ); + } + else { + data.uniqueKeyPropertyTypes = null; + } + data.canUseEmbeddedIdentifierInstanceAsEntity = data.getRowProcessingState().getEntityId() != null + // The id can only be the entity instance if this is a non-aggregated id that has no containing class + && entityDescriptor.getIdentifierMapping() instanceof CompositeIdentifierMapping + && !( (CompositeIdentifierMapping) entityDescriptor.getIdentifierMapping() ).hasContainingClass(); + } + else { + data.uniqueKeyAttributePath = null; + data.uniqueKeyPropertyTypes = null; + data.canUseEmbeddedIdentifierInstanceAsEntity = false; + } + data.hasCallbackActions = rowProcessingState.hasCallbackActions(); + forEachSubInitializer( Initializer::startLoading, data ); + } + + protected Type[] getParentEntityAttributeTypes(String attributeName) { + final Type[] attributeTypes = new Type[ + entityDescriptor.getRootEntityDescriptor() + .getSubclassEntityNames() + .size() + ]; + initializeAttributeType( attributeTypes, entityDescriptor, attributeName ); + for ( EntityMappingType subMappingType : entityDescriptor.getSubMappingTypes() ) { + initializeAttributeType( attributeTypes, subMappingType.getEntityPersister(), attributeName ); + } + return attributeTypes; + } + + protected void initializeAttributeType(Type[] attributeTypes, EntityPersister entityDescriptor, String attributeName) { + if ( entityDescriptor.findByPath( attributeName ) != null ) { + attributeTypes[entityDescriptor.getSubclassId()] = entityDescriptor.getPropertyType( attributeName ); } - super.startLoading( rowProcessingState ); } public static @Nullable EntityPersister determineConcreteEntityDescriptor( @@ -592,245 +628,236 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity } } - private boolean useEmbeddedIdentifierInstanceAsEntity(Object id, RowProcessingState rowProcessingState) { - return id != null && isResultInitializer() - // The id can only be the entity instance if this is a non-aggregated id that has no containing class - && entityDescriptor.getIdentifierMapping() instanceof CompositeIdentifierMapping - && !( (CompositeIdentifierMapping) entityDescriptor.getIdentifierMapping() ).hasContainingClass() - && ( concreteDescriptor = determineConcreteEntityDescriptor( rowProcessingState, discriminatorAssembler, entityDescriptor ) ) != null - && concreteDescriptor.isInstance( id ); + private boolean useEmbeddedIdentifierInstanceAsEntity(EntityInitializerData data) { + return data.canUseEmbeddedIdentifierInstanceAsEntity + && ( data.concreteDescriptor = determineConcreteEntityDescriptor( data.getRowProcessingState(), discriminatorAssembler, entityDescriptor ) ) != null + && data.concreteDescriptor.isInstance( data.getRowProcessingState().getEntityId() ); } @Override - public void resolveInstance(Object instance) { + public void resolveInstance(Object instance, EntityInitializerData data) { if ( instance == null ) { - setMissing( rowProcessingState ); + setMissing( data ); return; } - entityInstance = instance; - final LazyInitializer lazyInitializer = extractLazyInitializer( entityInstance ); + data.setInstance( instance ); + final LazyInitializer lazyInitializer = extractLazyInitializer( data.getInstance() ); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); final SharedSessionContractImplementor session = rowProcessingState.getSession(); if ( lazyInitializer == null ) { // Entity is most probably initialized - entityInstanceForNotify = entityInstance; - concreteDescriptor = session.getEntityPersister( null, entityInstance ); + data.entityInstanceForNotify = data.getInstance(); + data.concreteDescriptor = session.getEntityPersister( null, data.getInstance() ); resolveEntityKey( - rowProcessingState, - concreteDescriptor.getIdentifier( entityInstance, session ) + data, + data.concreteDescriptor.getIdentifier( data.getInstance(), session ) ); - entityHolder = session.getPersistenceContextInternal().getEntityHolder( entityKey ); + data.entityHolder = session.getPersistenceContextInternal().getEntityHolder( data.entityKey ); // If the entity initializer is null, we know the entity is fully initialized, // otherwise it will be initialized by some other initializer - state = entityHolder.getEntityInitializer() == null ? State.INITIALIZED : State.RESOLVED; + data.setState( data.entityHolder.getEntityInitializer() == null ? State.INITIALIZED : State.RESOLVED ); } else if ( lazyInitializer.isUninitialized() ) { - state = State.RESOLVED; + data.setState( State.RESOLVED ); // Read the discriminator from the result set if necessary - concreteDescriptor = discriminatorAssembler == null + data.concreteDescriptor = discriminatorAssembler == null ? entityDescriptor : determineConcreteEntityDescriptor( rowProcessingState, discriminatorAssembler, entityDescriptor ); - assert concreteDescriptor != null; - resolveEntityKey( rowProcessingState, lazyInitializer.getIdentifier() ); - entityHolder = session.getPersistenceContextInternal().claimEntityHolderIfPossible( - entityKey, + assert data.concreteDescriptor != null; + resolveEntityKey( data, lazyInitializer.getIdentifier() ); + data.entityHolder = session.getPersistenceContextInternal().claimEntityHolderIfPossible( + data.entityKey, null, rowProcessingState.getJdbcValuesSourceProcessingState(), this ); // Resolve and potentially create the entity instance - entityInstanceForNotify = resolveEntityInstance( rowProcessingState ); - lazyInitializer.setImplementation( entityInstanceForNotify ); - registerLoadingEntity( rowProcessingState, entityInstanceForNotify ); + data.entityInstanceForNotify = resolveEntityInstance( data ); + lazyInitializer.setImplementation( data.entityInstanceForNotify ); + registerLoadingEntity( data, data.entityInstanceForNotify ); } else { - state = State.INITIALIZED; - entityInstanceForNotify = lazyInitializer.getImplementation(); - concreteDescriptor = session.getEntityPersister( null, entityInstanceForNotify ); - resolveEntityKey( rowProcessingState, lazyInitializer.getIdentifier() ); - entityHolder = session.getPersistenceContextInternal().getEntityHolder( entityKey ); + data.setState( State.INITIALIZED ); + data.entityInstanceForNotify = lazyInitializer.getImplementation(); + data.concreteDescriptor = session.getEntityPersister( null, data.entityInstanceForNotify ); + resolveEntityKey( data, lazyInitializer.getIdentifier() ); + data.entityHolder = session.getPersistenceContextInternal().getEntityHolder( data.entityKey ); } if ( identifierAssembler != null ) { - final Initializer initializer = identifierAssembler.getInitializer(); + final Initializer initializer = identifierAssembler.getInitializer(); if ( initializer != null ) { - initializer.resolveInstance( entityKey.getIdentifier() ); + initializer.resolveInstance( data.entityKey.getIdentifier(), rowProcessingState ); } } - upgradeLockMode( rowProcessingState ); - if ( state == State.INITIALIZED ) { - registerReloadedEntity( rowProcessingState ); - resolveInstanceSubInitializers( rowProcessingState ); - if ( !rowProcessingState.isQueryCacheHit() && rowProcessingState.getQueryOptions().isResultCachingEnabled() == Boolean.TRUE ) { + upgradeLockMode( data ); + if ( data.getState() == State.INITIALIZED ) { + registerReloadedEntity( data ); + resolveInstanceSubInitializers( data ); + if ( rowProcessingState.needsResolveState() ) { // We need to read result set values to correctly populate the query cache - resolveState( rowProcessingState ); + resolveState( data ); } } else { - resolveKeySubInitializers( rowProcessingState ); + resolveKeySubInitializers( data ); } } @Override - public void resolveInstance() { - if ( state != State.KEY_RESOLVED ) { + public void resolveInstance(EntityInitializerData data) { + if ( data.getState() != State.KEY_RESOLVED ) { return; } - state = State.RESOLVED; - if ( entityKey == null ) { + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + data.setState( State.RESOLVED ); + if ( data.entityKey == null ) { assert identifierAssembler != null; final Object id = identifierAssembler.assemble( rowProcessingState ); if ( id == null ) { - setMissing( rowProcessingState ); + setMissing( data ); return; } - resolveEntityKey( rowProcessingState, id ); + resolveEntityKey( data, id ); } final PersistenceContext persistenceContext = rowProcessingState.getSession() .getPersistenceContextInternal(); - entityHolder = persistenceContext.claimEntityHolderIfPossible( - entityKey, + data.entityHolder = persistenceContext.claimEntityHolderIfPossible( + data.entityKey, null, rowProcessingState.getJdbcValuesSourceProcessingState(), this ); - if ( useEmbeddedIdentifierInstanceAsEntity( rowProcessingState.getEntityId(), rowProcessingState ) ) { - entityInstance = entityInstanceForNotify = rowProcessingState.getEntityId(); + if ( useEmbeddedIdentifierInstanceAsEntity( data ) ) { + data.setInstance( data.entityInstanceForNotify = rowProcessingState.getEntityId() ); } else { - resolveEntityInstance1( rowProcessingState ); - if ( isResultInitializer() ) { - final String uniqueKeyAttributePath = rowProcessingState.getEntityUniqueKeyAttributePath(); - if ( uniqueKeyAttributePath != null ) { - final SharedSessionContractImplementor session = rowProcessingState.getSession(); - final EntityUniqueKey euk = new EntityUniqueKey( - getConcreteDescriptor().getEntityName(), - uniqueKeyAttributePath, - rowProcessingState.getEntityUniqueKey(), - getConcreteDescriptor().getPropertyType( uniqueKeyAttributePath ), - session.getFactory() - ); - session.getPersistenceContextInternal().addEntity( euk, getEntityInstance() ); - } + resolveEntityInstance1( data ); + if ( data.uniqueKeyAttributePath != null ) { + final SharedSessionContractImplementor session = rowProcessingState.getSession(); + final EntityPersister concreteDescriptor = getConcreteDescriptor( data ); + final EntityUniqueKey euk = new EntityUniqueKey( + concreteDescriptor.getEntityName(), + data.uniqueKeyAttributePath, + rowProcessingState.getEntityUniqueKey(), + data.uniqueKeyPropertyTypes[concreteDescriptor.getSubclassId()], + session.getFactory() + ); + session.getPersistenceContextInternal().addEntity( euk, getEntityInstance( data ) ); } } - if ( entityInstance != null ) { - upgradeLockMode( rowProcessingState ); - if ( state == State.INITIALIZED ) { - registerReloadedEntity( rowProcessingState ); - if ( !rowProcessingState.isQueryCacheHit() && rowProcessingState.getQueryOptions().isResultCachingEnabled() == Boolean.TRUE ) { + if ( data.getInstance() != null ) { + upgradeLockMode( data ); + if ( data.getState() == State.INITIALIZED ) { + registerReloadedEntity( data ); + if ( rowProcessingState.needsResolveState() ) { // We need to read result set values to correctly populate the query cache - resolveState( rowProcessingState ); + resolveState( data ); } } - if ( shallowCached ) { - initializeSubInstancesFromParent( rowProcessingState ); + if ( data.shallowCached ) { + initializeSubInstancesFromParent( data ); } } } - protected void resolveEntityInstance1(RowProcessingState rowProcessingState) { - if ( EntityLoadingLogging.ENTITY_LOADING_LOGGER.isTraceEnabled() ) { - EntityLoadingLogging.ENTITY_LOADING_LOGGER.tracef( - "(%s) Beginning Initializer#resolveInstance process for entity (%s) : %s", - StringHelper.collapse( this.getClass().getName() ), - getNavigablePath(), - entityKey.getIdentifier() - ); - } - - final Object proxy = entityHolder.getProxy(); + protected void resolveEntityInstance1(EntityInitializerData data) { + final Object proxy = data.entityHolder.getProxy(); final boolean unwrapProxy = proxy != null && referencedModelPart instanceof ToOneAttributeMapping && ( (ToOneAttributeMapping) referencedModelPart ).isUnwrapProxy() - && getConcreteDescriptor().getBytecodeEnhancementMetadata().isEnhancedForLazyLoading(); + && getConcreteDescriptor( data ).getBytecodeEnhancementMetadata().isEnhancedForLazyLoading(); final Object entityFromExecutionContext; if ( !unwrapProxy && isProxyInstance( proxy ) ) { - if ( ( entityFromExecutionContext = getEntityFromExecutionContext( rowProcessingState ) ) != null ) { - entityInstance = entityInstanceForNotify = entityFromExecutionContext; + if ( ( entityFromExecutionContext = getEntityFromExecutionContext( data ) ) != null ) { + data.setInstance( data.entityInstanceForNotify = entityFromExecutionContext ); // If the entity comes from the execution context, it is treated as not initialized // so that we can refresh the data as requested - registerReloadedEntity( rowProcessingState ); + registerReloadedEntity( data ); } else { - entityInstance = proxy; - if ( Hibernate.isInitialized( entityInstance ) ) { - state = State.INITIALIZED; - entityInstanceForNotify = Hibernate.unproxy( entityInstance ); + data.setInstance( proxy ); + if ( Hibernate.isInitialized( data.getInstance() ) ) { + data.setState( State.INITIALIZED ); + data.entityInstanceForNotify = Hibernate.unproxy( data.getInstance() ); } else { - final LazyInitializer lazyInitializer = extractLazyInitializer( entityInstance ); + final LazyInitializer lazyInitializer = extractLazyInitializer( data.getInstance() ); assert lazyInitializer != null; - entityInstanceForNotify = resolveInstance( entityHolder, rowProcessingState ); - lazyInitializer.setImplementation( entityInstanceForNotify ); + data.entityInstanceForNotify = resolveEntityInstance2( data ); + lazyInitializer.setImplementation( data.entityInstanceForNotify ); } } } else { - final Object existingEntity = entityHolder.getEntity(); + final Object existingEntity = data.entityHolder.getEntity(); if ( existingEntity != null ) { - entityInstance = entityInstanceForNotify = existingEntity; - if ( entityHolder.getEntityInitializer() == null ) { - if ( isExistingEntityInitialized( existingEntity ) ) { - state = State.INITIALIZED; + data.setInstance( data.entityInstanceForNotify = existingEntity ); + if ( data.entityHolder.getEntityInitializer() == null ) { + assert data.entityHolder.isInitialized() == isExistingEntityInitialized( existingEntity ); + if ( data.entityHolder.isInitialized() ) { + data.setState( State.INITIALIZED ); } else if ( isResultInitializer() ) { - registerLoadingEntity( rowProcessingState, entityInstance ); + registerLoadingEntity( data, data.getInstance() ); } } - else if ( entityHolder.getEntityInitializer() != this ) { - state = State.INITIALIZED; + else if ( data.entityHolder.getEntityInitializer() != this ) { + data.setState( State.INITIALIZED ); } } - else if ( ( entityFromExecutionContext = getEntityFromExecutionContext( rowProcessingState ) ) != null ) { + else if ( ( entityFromExecutionContext = getEntityFromExecutionContext( data ) ) != null ) { // This is the entity to refresh, so don't set the state to initialized - entityInstance = entityInstanceForNotify = entityFromExecutionContext; + data.setInstance( data.entityInstanceForNotify = entityFromExecutionContext ); if ( isResultInitializer() ) { - registerLoadingEntity( rowProcessingState, entityInstance ); + registerLoadingEntity( data, data.getInstance() ); } } else { - assert entityHolder.getEntityInitializer() == this; + assert data.entityHolder.getEntityInitializer() == this; // look to see if another initializer from a parent load context or an earlier // initializer is already loading the entity - entityInstance = entityInstanceForNotify = resolveInstance( entityHolder, rowProcessingState ); - final Initializer idInitializer; - if ( entityHolder.getEntityInitializer() == this && !isEntityInitialized() + data.setInstance( data.entityInstanceForNotify = resolveEntityInstance2( data ) ); + final Initializer idInitializer; + if ( data.entityHolder.getEntityInitializer() == this && data.getState() != State.INITIALIZED && identifierAssembler != null && ( idInitializer = identifierAssembler.getInitializer() ) != null ) { // If this is the owning initializer and the returned object is not initialized, // this means that the entity instance was just instantiated. // In this case, we want to call "assemble" and hence "initializeInstance" on the initializer // for possibly non-aggregated identifier mappings, so inject the virtual id representation - idInitializer.initializeInstance(); + idInitializer.initializeInstance( data.getRowProcessingState() ); } } } // todo: ensure we initialize the entity - assert !shallowCached || state == State.INITIALIZED : "Forgot to initialize the entity"; + assert !data.shallowCached || data.getState() == State.INITIALIZED : "Forgot to initialize the entity"; } - protected Object getEntityFromExecutionContext(RowProcessingState rowProcessingState) { + protected Object getEntityFromExecutionContext(EntityInitializerData data) { + final RowProcessingState rowProcessingState = data.getRowProcessingState(); final ExecutionContext executionContext = rowProcessingState.getJdbcValuesSourceProcessingState() .getExecutionContext(); if ( rootEntityDescriptor == executionContext.getRootEntityDescriptor() - && entityKey.getIdentifier().equals( executionContext.getEntityId() ) ) { + && data.entityKey.getIdentifier().equals( executionContext.getEntityId() ) ) { return executionContext.getEntityInstance(); } return null; } - private void upgradeLockMode(RowProcessingState rowProcessingState) { - if ( lockMode != LockMode.NONE && rowProcessingState.upgradeLocks() ) { - final EntityEntry entry = - rowProcessingState.getSession().getPersistenceContextInternal() - .getEntry( entityInstanceForNotify ); - if ( entry != null && entry.getLockMode().lessThan( lockMode ) ) { + private void upgradeLockMode(EntityInitializerData data) { + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + if ( data.lockMode != LockMode.NONE && rowProcessingState.upgradeLocks() ) { + final EntityEntry entry = data.entityHolder.getEntityEntry(); + assert entry == rowProcessingState.getSession().getPersistenceContextInternal() + .getEntry( data.entityInstanceForNotify ); + if ( entry != null && entry.getLockMode().lessThan( data.lockMode ) ) { //we only check the version when _upgrading_ lock modes if ( versionAssembler != null && entry.getLockMode() != LockMode.NONE ) { - checkVersion( entry, rowProcessingState ); + checkVersion( data, entry, rowProcessingState ); } //we need to upgrade the lock mode to the mode requested - entry.setLockMode( lockMode ); + entry.setLockMode( data.lockMode ); } } } @@ -849,17 +876,20 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity * the object version in the session cache, throwing an exception * if the version numbers are different */ - private void checkVersion(EntityEntry entry, final RowProcessingState rowProcessingState) throws HibernateException { + private void checkVersion( + EntityInitializerData data, + EntityEntry entry, + final RowProcessingState rowProcessingState) throws HibernateException { final Object version = entry.getVersion(); if ( version != null ) { // null version means the object is in the process of being loaded somewhere else in the ResultSet final Object currentVersion = versionAssembler.assemble( rowProcessingState ); - if ( !concreteDescriptor.getVersionType().isEqual( version, currentVersion ) ) { + if ( !data.concreteDescriptor.getVersionType().isEqual( version, currentVersion ) ) { final StatisticsImplementor statistics = rowProcessingState.getSession().getFactory().getStatistics(); if ( statistics.isStatisticsEnabled() ) { - statistics.optimisticFailure( concreteDescriptor.getEntityName() ); + statistics.optimisticFailure( data.concreteDescriptor.getEntityName() ); } - throw new StaleObjectStateException( concreteDescriptor.getEntityName(), entry.getId() ); + throw new StaleObjectStateException( data.concreteDescriptor.getEntityName(), entry.getId() ); } } @@ -868,261 +898,238 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity /** * Used by Hibernate Reactive */ - protected Object resolveInstance(EntityHolder holder, RowProcessingState rowProcessingState) { - if ( entityHolder.getEntityInitializer() == this ) { - assert holder.getEntity() == null; - return resolveEntityInstance( rowProcessingState ); + protected Object resolveEntityInstance2(EntityInitializerData data) { + if ( data.entityHolder.getEntityInitializer() == this ) { + assert data.entityHolder.getEntity() == null; + return resolveEntityInstance( data ); } else { // the entity is already being loaded elsewhere - if ( EntityLoadingLogging.ENTITY_LOADING_LOGGER.isDebugEnabled() ) { - EntityLoadingLogging.ENTITY_LOADING_LOGGER.debugf( - "(%s) Entity [%s] being loaded by another initializer [%s] - skipping processing", - getSimpleConcreteImplName(), - toLoggableString( getNavigablePath(), entityKey.getIdentifier() ), - holder.getEntityInitializer() - ); - } - return holder.getEntity(); + return data.entityHolder.getEntity(); } } - protected Object resolveEntityInstance(RowProcessingState rowProcessingState) { - final Object resolved = resolveToOptionalInstance( rowProcessingState ); + protected Object resolveEntityInstance(EntityInitializerData data) { + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final Object resolved = resolveToOptionalInstance( data ); if ( resolved != null ) { - registerLoadingEntity( rowProcessingState, resolved ); + registerLoadingEntity( data, resolved ); return resolved; } else { if ( rowProcessingState.isQueryCacheHit() && entityDescriptor.useShallowQueryCacheLayout() ) { // We must load the entity this way, because the query cache entry contains only the primary key - state = State.INITIALIZED; + data.setState( State.INITIALIZED ); final SharedSessionContractImplementor session = rowProcessingState.getSession(); - assert entityHolder.getEntityInitializer() == this; + assert data.entityHolder.getEntityInitializer() == this; // If this initializer owns the entity, we have to remove the entity holder, // because the subsequent loading process will claim the entity - session.getPersistenceContextInternal().removeEntityHolder( entityKey ); + session.getPersistenceContextInternal().removeEntityHolder( data.entityKey ); return session.internalLoad( - concreteDescriptor.getEntityName(), - entityKey.getIdentifier(), + data.concreteDescriptor.getEntityName(), + data.entityKey.getIdentifier(), true, false ); } // We have to query the second level cache if reference cache entries are used else if ( entityDescriptor.canUseReferenceCacheEntries() ) { - final Object cached = resolveInstanceFromCache( rowProcessingState ); + final Object cached = resolveInstanceFromCache( data ); if ( cached != null ) { // EARLY EXIT!!! // because the second level cache has reference cache entries, the entity is initialized - state = State.INITIALIZED; + data.setState( State.INITIALIZED ); return cached; } } - final Object instance = instantiateEntity( rowProcessingState.getSession() ); - registerLoadingEntity( rowProcessingState, instance ); + final Object instance = instantiateEntity( data ); + registerLoadingEntity( data, instance ); return instance; } } - protected Object instantiateEntity(SharedSessionContractImplementor session) { - final Object instance = session.instantiate( concreteDescriptor, entityKey.getIdentifier() ); - if ( EntityLoadingLogging.ENTITY_LOADING_LOGGER.isDebugEnabled() ) { - EntityLoadingLogging.ENTITY_LOADING_LOGGER.debugf( - "(%s) Created new entity instance [%s] : %s", - getSimpleConcreteImplName(), - toLoggableString( getNavigablePath(), entityKey.getIdentifier() ), - System.identityHashCode( instance ) - ); - } + protected Object instantiateEntity(EntityInitializerData data) { + final Object instance = data.getRowProcessingState().getSession() + .instantiate( data.concreteDescriptor, data.entityKey.getIdentifier() ); return instance; } - private Object resolveToOptionalInstance(RowProcessingState rowProcessingState) { + private Object resolveToOptionalInstance(EntityInitializerData data) { if ( isResultInitializer() ) { // this isEntityReturn bit is just for entity loaders, not hql/criteria final JdbcValuesSourceProcessingOptions processingOptions = - rowProcessingState.getJdbcValuesSourceProcessingState().getProcessingOptions(); - return matchesOptionalInstance( processingOptions ) ? processingOptions.getEffectiveOptionalObject() : null; + data.getRowProcessingState().getJdbcValuesSourceProcessingState().getProcessingOptions(); + return matchesOptionalInstance( data, processingOptions ) ? processingOptions.getEffectiveOptionalObject() : null; } else { return null; } } - private boolean matchesOptionalInstance(JdbcValuesSourceProcessingOptions processingOptions) { + private boolean matchesOptionalInstance( + EntityInitializerData data, + JdbcValuesSourceProcessingOptions processingOptions) { final Object optionalEntityInstance = processingOptions.getEffectiveOptionalObject(); final Object requestedEntityId = processingOptions.getEffectiveOptionalId(); return requestedEntityId != null && optionalEntityInstance != null - && requestedEntityId.equals( entityKey.getIdentifier() ); + && requestedEntityId.equals( data.entityKey.getIdentifier() ); } - private Object resolveInstanceFromCache(RowProcessingState rowProcessingState) { + private Object resolveInstanceFromCache(EntityInitializerData data) { return CacheEntityLoaderHelper.INSTANCE.loadFromSecondLevelCache( - rowProcessingState.getSession().asEventSource(), + data.getRowProcessingState().getSession().asEventSource(), null, - lockMode, + data.lockMode, entityDescriptor, - entityKey + data.entityKey ); } - protected void registerLoadingEntity(RowProcessingState rowProcessingState, Object instance) { - rowProcessingState.getSession().getPersistenceContextInternal().claimEntityHolderIfPossible( - entityKey, + protected void registerLoadingEntity(EntityInitializerData data, Object instance) { + data.getRowProcessingState().getSession().getPersistenceContextInternal().claimEntityHolderIfPossible( + data.entityKey, instance, - rowProcessingState.getJdbcValuesSourceProcessingState(), + data.getRowProcessingState().getJdbcValuesSourceProcessingState(), this ); } - protected void registerReloadedEntity(RowProcessingState rowProcessingState) { - if ( rowProcessingState.hasCallbackActions() ) { + protected void registerReloadedEntity(EntityInitializerData data) { + if ( data.hasCallbackActions ) { // This is only needed for follow-on locking, so skip registering the entity if there is no callback - entityHolder.markAsReloaded( rowProcessingState.getJdbcValuesSourceProcessingState() ); + data.entityHolder.markAsReloaded( data.getRowProcessingState().getJdbcValuesSourceProcessingState() ); } } @Override - public void initializeInstance() { - if ( state != State.RESOLVED ) { + public void initializeInstance(EntityInitializerData data) { + if ( data.getState() != State.RESOLVED ) { return; } - if ( !skipInitialization( rowProcessingState ) ) { - assert consistentInstance( rowProcessingState ); - initializeEntityInstance( rowProcessingState ); + if ( !skipInitialization( data ) ) { + assert consistentInstance( data ); + initializeEntityInstance( data ); } - state = State.INITIALIZED; + data.setState( State.INITIALIZED ); } - protected boolean consistentInstance(RowProcessingState rowProcessingState) { + protected boolean consistentInstance(EntityInitializerData data) { final PersistenceContext persistenceContextInternal = - rowProcessingState.getSession().getPersistenceContextInternal(); + data.getRowProcessingState().getSession().getPersistenceContextInternal(); // Only call PersistenceContext#getEntity within the assert expression, as it is costly - final Object entity = persistenceContextInternal.getEntity( entityKey ); - return entity == null || entity == entityInstanceForNotify; + final Object entity = persistenceContextInternal.getEntity( data.entityKey ); + return entity == null || entity == data.entityInstanceForNotify; } - private void initializeEntityInstance(RowProcessingState rowProcessingState) { - final Object entityIdentifier = entityKey.getIdentifier(); + private void initializeEntityInstance(EntityInitializerData data) { + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final Object entityIdentifier = data.entityKey.getIdentifier(); final SharedSessionContractImplementor session = rowProcessingState.getSession(); final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); - if ( EntityLoadingLogging.ENTITY_LOADING_LOGGER.isTraceEnabled() ) { - EntityLoadingLogging.ENTITY_LOADING_LOGGER.tracef( - "(%s) Beginning Initializer#initializeInstance process for entity %s", - getSimpleConcreteImplName(), - toLoggableString( getNavigablePath(), entityIdentifier ) - ); - } + final Object[] resolvedEntityState = extractConcreteTypeStateValues( data ); - final Object[] resolvedEntityState = extractConcreteTypeStateValues( rowProcessingState ); + preLoad( data, resolvedEntityState ); - preLoad( rowProcessingState, resolvedEntityState ); - - if ( isPersistentAttributeInterceptable( entityInstanceForNotify ) ) { + if ( isPersistentAttributeInterceptable( data.entityInstanceForNotify ) ) { final PersistentAttributeInterceptor persistentAttributeInterceptor = - asPersistentAttributeInterceptable( entityInstanceForNotify ).$$_hibernate_getInterceptor(); + asPersistentAttributeInterceptable( data.entityInstanceForNotify ).$$_hibernate_getInterceptor(); if ( persistentAttributeInterceptor == null || persistentAttributeInterceptor instanceof EnhancementAsProxyLazinessInterceptor ) { // if we do this after the entity has been initialized the // BytecodeLazyAttributeInterceptor#isAttributeLoaded(String fieldName) would return false; - concreteDescriptor.getBytecodeEnhancementMetadata() - .injectInterceptor( entityInstanceForNotify, entityIdentifier, session ); + data.concreteDescriptor.getBytecodeEnhancementMetadata() + .injectInterceptor( data.entityInstanceForNotify, entityIdentifier, session ); } } - concreteDescriptor.setPropertyValues( entityInstanceForNotify, resolvedEntityState ); + data.concreteDescriptor.setPropertyValues( data.entityInstanceForNotify, resolvedEntityState ); - persistenceContext.addEntity( entityKey, entityInstanceForNotify ); + persistenceContext.addEntity( data.entityKey, data.entityInstanceForNotify ); // Also register possible unique key entries - registerPossibleUniqueKeyEntries( resolvedEntityState, session ); + registerPossibleUniqueKeyEntries( data, resolvedEntityState, session ); final Object version = versionAssembler != null ? versionAssembler.assemble( rowProcessingState ) : null; final Object rowId = rowIdAssembler != null ? rowIdAssembler.assemble( rowProcessingState ) : null; // from the perspective of Hibernate, an entity is read locked as soon as it is read // so regardless of the requested lock mode, we upgrade to at least the read level - final LockMode lockModeToAcquire = lockMode == LockMode.NONE ? LockMode.READ : lockMode; + final LockMode lockModeToAcquire = data.lockMode == LockMode.NONE ? LockMode.READ : data.lockMode; final EntityEntry entityEntry = persistenceContext.addEntry( - entityInstanceForNotify, + data.entityInstanceForNotify, Status.LOADING, resolvedEntityState, rowId, - entityKey.getIdentifier(), + data.entityKey.getIdentifier(), version, lockModeToAcquire, true, - concreteDescriptor, + data.concreteDescriptor, false ); + data.entityHolder.setEntityEntry( entityEntry ); - registerNaturalIdResolution( persistenceContext, resolvedEntityState ); + registerNaturalIdResolution( data, persistenceContext, resolvedEntityState ); - takeSnapshot( rowProcessingState, session, persistenceContext, entityEntry, resolvedEntityState ); + takeSnapshot( data, session, persistenceContext, entityEntry, resolvedEntityState ); - concreteDescriptor.afterInitialize( entityInstanceForNotify, session ); + data.concreteDescriptor.afterInitialize( data.entityInstanceForNotify, session ); - if ( EntityLoadingLogging.ENTITY_LOADING_LOGGER.isDebugEnabled() ) { - EntityLoadingLogging.ENTITY_LOADING_LOGGER.debugf( - "(%s) Done materializing entityInstance : %s", - getSimpleConcreteImplName(), - toLoggableString( getNavigablePath(), entityIdentifier ) - ); - } - - assert concreteDescriptor.getIdentifier( entityInstanceForNotify, session ) != null; + assert data.concreteDescriptor.getIdentifier( data.entityInstanceForNotify, session ) != null; final StatisticsImplementor statistics = session.getFactory().getStatistics(); if ( statistics.isStatisticsEnabled() ) { if ( !rowProcessingState.isQueryCacheHit() ) { - statistics.loadEntity( concreteDescriptor.getEntityName() ); + statistics.loadEntity( data.concreteDescriptor.getEntityName() ); } } updateCaches( - rowProcessingState, + data, session, - session.getPersistenceContext(), + session.getPersistenceContextInternal(), resolvedEntityState, version ); } protected void updateCaches( - RowProcessingState rowProcessingState, + EntityInitializerData data, SharedSessionContractImplementor session, PersistenceContext persistenceContext, Object[] resolvedEntityState, Object version) { - if ( concreteDescriptor.canWriteToCache() + if ( data.concreteDescriptor.canWriteToCache() // No need to put into the entity cache if this is coming from the query cache already - && !rowProcessingState.isQueryCacheHit() + && !data.getRowProcessingState().isQueryCacheHit() && session.getCacheMode().isPutEnabled() ) { - final EntityDataAccess cacheAccess = concreteDescriptor.getCacheAccessStrategy(); + final EntityDataAccess cacheAccess = data.concreteDescriptor.getCacheAccessStrategy(); if ( cacheAccess != null ) { - putInCache( session, persistenceContext, resolvedEntityState, version, cacheAccess ); + putInCache( data, session, persistenceContext, resolvedEntityState, version, cacheAccess ); } } } - protected void registerNaturalIdResolution(PersistenceContext persistenceContext, Object[] resolvedEntityState) { + protected void registerNaturalIdResolution( + EntityInitializerData data, + PersistenceContext persistenceContext, + Object[] resolvedEntityState) { if ( entityDescriptor.getNaturalIdMapping() != null ) { final Object naturalId = entityDescriptor.getNaturalIdMapping().extractNaturalIdFromEntityState( resolvedEntityState ); persistenceContext.getNaturalIdResolutions() - .cacheResolutionFromLoad( entityKey.getIdentifier(), naturalId, entityDescriptor ); + .cacheResolutionFromLoad( data.entityKey.getIdentifier(), naturalId, entityDescriptor ); } } protected void takeSnapshot( - RowProcessingState rowProcessingState, + EntityInitializerData data, SharedSessionContractImplementor session, PersistenceContext persistenceContext, EntityEntry entityEntry, Object[] resolvedEntityState) { - if ( isReallyReadOnly( rowProcessingState, session ) ) { + if ( isReallyReadOnly( data, session ) ) { //no need to take a snapshot - this is a //performance optimization, but not really //important, except for entities with huge @@ -1131,29 +1138,30 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity } else { //take a snapshot - deepCopy( concreteDescriptor, resolvedEntityState, resolvedEntityState ); + deepCopy( data.concreteDescriptor, resolvedEntityState, resolvedEntityState ); persistenceContext.setEntryStatus( entityEntry, Status.MANAGED ); } } - private boolean isReallyReadOnly(RowProcessingState rowProcessingState, SharedSessionContractImplementor session) { - if ( !concreteDescriptor.isMutable() ) { + private boolean isReallyReadOnly(EntityInitializerData data, SharedSessionContractImplementor session) { + if ( !data.concreteDescriptor.isMutable() ) { return true; } else { - final LazyInitializer lazyInitializer = extractLazyInitializer( entityInstance ); + final LazyInitializer lazyInitializer = extractLazyInitializer( data.getInstance() ); if ( lazyInitializer != null ) { // there is already a proxy for this impl // only set the status to read-only if the proxy is read-only return lazyInitializer.isReadOnly(); } else { - return isReadOnly( rowProcessingState, session ); + return isReadOnly( data.getRowProcessingState(), session ); } } } private void putInCache( + EntityInitializerData data, SharedSessionContractImplementor session, PersistenceContext persistenceContext, Object[] resolvedEntityState, @@ -1161,22 +1169,14 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity EntityDataAccess cacheAccess) { final SessionFactoryImplementor factory = session.getFactory(); - if ( EntityLoadingLogging.ENTITY_LOADING_LOGGER.isDebugEnabled() ) { - EntityLoadingLogging.ENTITY_LOADING_LOGGER.debugf( - "(%S) Adding entityInstance to second-level cache: %s", - getSimpleConcreteImplName(), - toLoggableString( getNavigablePath(), entityKey.getIdentifier() ) - ); - } - - final CacheEntry cacheEntry = concreteDescriptor.buildCacheEntry( - entityInstanceForNotify, + final CacheEntry cacheEntry = data.concreteDescriptor.buildCacheEntry( + data.entityInstanceForNotify, resolvedEntityState, version, session ); final Object cacheKey = cacheAccess.generateCacheKey( - entityKey.getIdentifier(), + data.entityKey.getIdentifier(), rootEntityDescriptor, factory, session.getTenantIdentifier() @@ -1189,14 +1189,14 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity // // we need to be careful not to clobber the lock here in the cache so that it can be rolled back if need be final EventManager eventManager = session.getEventManager(); - if ( persistenceContext.wasInsertedDuringTransaction( concreteDescriptor, entityKey.getIdentifier() ) ) { + if ( persistenceContext.wasInsertedDuringTransaction( data.concreteDescriptor, data.entityKey.getIdentifier() ) ) { boolean update = false; final HibernateMonitoringEvent cachePutEvent = eventManager.beginCachePutEvent(); try { update = cacheAccess.update( session, cacheKey, - concreteDescriptor.getCacheEntryStructure().structure( cacheEntry ), + data.concreteDescriptor.getCacheEntryStructure().structure( cacheEntry ), version, version ); @@ -1206,7 +1206,7 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity cachePutEvent, session, cacheAccess, - concreteDescriptor, + data.concreteDescriptor, update, EventManager.CacheActionDescription.ENTITY_UPDATE ); @@ -1221,7 +1221,7 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity put = cacheAccess.putFromLoad( session, cacheKey, - concreteDescriptor.getCacheEntryStructure().structure( cacheEntry ), + data.concreteDescriptor.getCacheEntryStructure().structure( cacheEntry ), version, //useMinimalPuts( session, entityEntry ) false @@ -1232,7 +1232,7 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity cachePutEvent, session, cacheAccess, - concreteDescriptor, + data.concreteDescriptor, put, EventManager.CacheActionDescription.ENTITY_LOAD ); @@ -1246,9 +1246,10 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity } protected void registerPossibleUniqueKeyEntries( + EntityInitializerData data, Object[] resolvedEntityState, final SharedSessionContractImplementor session) { - for ( UniqueKeyEntry entry : concreteDescriptor.uniqueKeyEntries() ) { + for ( UniqueKeyEntry entry : data.concreteDescriptor.uniqueKeyEntries() ) { final String ukName = entry.getUniqueKeyName(); final int index = entry.getStateArrayPosition(); final Type type = entry.getPropertyType(); @@ -1260,21 +1261,22 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity if ( resolvedEntityState[index] != null ) { final EntityUniqueKey entityUniqueKey = new EntityUniqueKey( - concreteDescriptor.getRootEntityDescriptor().getEntityName(), + data.concreteDescriptor.getRootEntityDescriptor().getEntityName(), //polymorphism comment above ukName, resolvedEntityState[index], type, session.getFactory() ); - session.getPersistenceContextInternal().addEntity( entityUniqueKey, entityInstanceForNotify ); + session.getPersistenceContextInternal().addEntity( entityUniqueKey, data.entityInstanceForNotify ); } } } - protected Object[] extractConcreteTypeStateValues(RowProcessingState rowProcessingState) { - final Object[] values = new Object[concreteDescriptor.getNumberOfAttributeMappings()]; - final DomainResultAssembler[] concreteAssemblers = assemblers[concreteDescriptor.getSubclassId()]; + protected Object[] extractConcreteTypeStateValues(EntityInitializerData data) { + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final Object[] values = new Object[data.concreteDescriptor.getNumberOfAttributeMappings()]; + final DomainResultAssembler[] concreteAssemblers = assemblers[data.concreteDescriptor.getSubclassId()]; for ( int i = 0; i < values.length; i++ ) { final DomainResultAssembler assembler = concreteAssemblers[i]; values[i] = assembler == null ? UNFETCHED_PROPERTY : assembler.assemble( rowProcessingState ); @@ -1282,20 +1284,22 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity return values; } - private void resolveState(RowProcessingState rowProcessingState) { - for ( final DomainResultAssembler assembler : assemblers[concreteDescriptor.getSubclassId()] ) { + private void resolveState(EntityInitializerData data) { + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + for ( final DomainResultAssembler assembler : assemblers[data.concreteDescriptor.getSubclassId()] ) { if ( assembler != null ) { assembler.resolveState( rowProcessingState ); } } } - protected boolean skipInitialization(RowProcessingState rowProcessingState) { - if ( entityHolder.getEntityInitializer() != this ) { + protected boolean skipInitialization(EntityInitializerData data) { + if ( data.entityHolder.getEntityInitializer() != this ) { return true; } - final EntityEntry entry = - rowProcessingState.getSession().getPersistenceContextInternal().getEntry( entityInstanceForNotify ); + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + final EntityEntry entry = data.entityHolder.getEntityEntry(); + assert entry == rowProcessingState.getSession().getPersistenceContextInternal().getEntry( data.entityInstanceForNotify ); if ( entry == null ) { return false; } @@ -1304,9 +1308,9 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity return true; } else { - if ( isPersistentAttributeInterceptable( entityInstanceForNotify ) ) { + if ( isPersistentAttributeInterceptable( data.entityInstanceForNotify ) ) { final PersistentAttributeInterceptor interceptor = - asPersistentAttributeInterceptable( entityInstanceForNotify ).$$_hibernate_getInterceptor(); + asPersistentAttributeInterceptable( data.entityInstanceForNotify ).$$_hibernate_getInterceptor(); if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor ) { // Avoid loading the same entity proxy twice for the same result set: it could lead to errors, // because some code writes to its input (ID in hydrated state replaced by the loaded entity, in particular). @@ -1320,7 +1324,7 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity // If the instance to initialize is the main entity, we can't skip this. // This can happen if we initialize an enhanced proxy. return rowProcessingState.getJdbcValuesSourceProcessingState().getProcessingOptions() - .getEffectiveOptionalObject() != entityInstanceForNotify; + .getEffectiveOptionalObject() != data.entityInstanceForNotify; } else { return false; @@ -1333,7 +1337,8 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity return readOnly == null ? persistenceContext.isDefaultReadOnly() : readOnly; } - protected void preLoad(RowProcessingState rowProcessingState, Object[] resolvedEntityState) { + protected void preLoad(EntityInitializerData data, Object[] resolvedEntityState) { + final RowProcessingState rowProcessingState = data.getRowProcessingState(); final SharedSessionContractImplementor session = rowProcessingState.getSession(); if ( session.isEventSource() ) { final PreLoadEvent preLoadEvent = rowProcessingState.getJdbcValuesSourceProcessingState().getPreLoadEvent(); @@ -1341,10 +1346,10 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity preLoadEvent.reset(); - preLoadEvent.setEntity( entityInstance ) + preLoadEvent.setEntity( data.getInstance() ) .setState( resolvedEntityState ) - .setId( entityKey.getIdentifier() ) - .setPersister( concreteDescriptor ); + .setId( data.entityKey.getIdentifier() ) + .setPersister( data.concreteDescriptor ); session.getFactory() .getFastSessionServices() @@ -1359,50 +1364,59 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity } @Override - public boolean isEntityInitialized() { - return state == State.INITIALIZED; + public EntityPersister getConcreteDescriptor(EntityInitializerData data) { + assert data.getState() != State.UNINITIALIZED; + return data.concreteDescriptor == null ? entityDescriptor : data.concreteDescriptor; } - @Override - public EntityPersister getConcreteDescriptor() { - assert state != State.UNINITIALIZED; - return concreteDescriptor == null ? entityDescriptor : concreteDescriptor; - } - - protected void initializeSubInstancesFromParent(RowProcessingState rowProcessingState) { - if ( entityInstanceForNotify != null ) { - for ( Initializer initializer : subInitializers[concreteDescriptor.getSubclassId()] ) { - initializer.initializeInstanceFromParent( entityInstanceForNotify ); + protected void initializeSubInstancesFromParent(EntityInitializerData data) { + if ( data.entityInstanceForNotify != null ) { + for ( Initializer initializer : subInitializers[data.concreteDescriptor.getSubclassId()] ) { + if (initializer != null) { + initializer.initializeInstanceFromParent( data.entityInstanceForNotify, data.getRowProcessingState() ); + } } } } @Override - protected void forEachSubInitializer(BiConsumer consumer, X arg) { - if ( identifierAssembler != null ) { - final Initializer initializer = identifierAssembler.getInitializer(); + protected void forEachSubInitializer(BiConsumer, RowProcessingState> consumer, InitializerData data) { + final RowProcessingState rowProcessingState = data.getRowProcessingState(); + if ( keyAssembler != null ) { + final Initializer initializer = keyAssembler.getInitializer(); if ( initializer != null ) { - consumer.accept( initializer, arg ); + consumer.accept( initializer, rowProcessingState ); } } - if ( concreteDescriptor == null ) { - for ( Initializer[] initializers : subInitializers ) { - for ( Initializer initializer : initializers ) { - consumer.accept( initializer, arg ); + if ( identifierAssembler != null ) { + final Initializer initializer = identifierAssembler.getInitializer(); + if ( initializer != null ) { + consumer.accept( initializer, rowProcessingState ); + } + } + final EntityInitializerData entityInitializerData = (EntityInitializerData) data; + if ( entityInitializerData.concreteDescriptor == null ) { + for ( Initializer[] initializers : subInitializers ) { + for ( Initializer initializer : initializers ) { + if ( initializer != null ) { + consumer.accept( initializer, rowProcessingState ); + } } } } else { - for ( Initializer initializer : subInitializers[concreteDescriptor.getSubclassId()] ) { - consumer.accept( initializer, arg ); + for ( Initializer initializer : subInitializers[entityInitializerData.concreteDescriptor.getSubclassId()] ) { + if ( initializer != null ) { + consumer.accept( initializer, rowProcessingState ); + } } } } @Override - public void endLoading(ExecutionContext executionContext) { - super.endLoading( executionContext ); - shallowCached = false; + public void endLoading(EntityInitializerData data) { + super.endLoading( data ); + data.shallowCached = false; } @Override @@ -1414,14 +1428,6 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity // For Hibernate Reactive //######################### - protected void setEntityInstanceForNotify(Object entityInstanceForNotify) { - this.entityInstanceForNotify = entityInstanceForNotify; - } - - protected Object getEntityInstanceForNotify() { - return entityInstanceForNotify; - } - protected DomainResultAssembler getVersionAssembler() { return versionAssembler; } @@ -1430,10 +1436,6 @@ public class EntityInitializerImpl extends AbstractInitializer implements Entity return rowIdAssembler; } - protected LockMode getLockMode() { - return lockMode; - } - protected DomainResultAssembler[][] getAssemblers() { return assemblers; } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityResultImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityResultImpl.java index 341f6a3a80..80808b1a36 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityResultImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityResultImpl.java @@ -6,7 +6,6 @@ */ package org.hibernate.sql.results.graph.entity.internal; -import org.hibernate.LockMode; import org.hibernate.annotations.NotFoundAction; import org.hibernate.metamodel.mapping.EntityValuedModelPart; import org.hibernate.spi.NavigablePath; @@ -15,7 +14,6 @@ import org.hibernate.sql.ast.tree.from.TableGroupJoin; import org.hibernate.sql.ast.tree.from.TableGroupProducer; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.graph.FetchableContainer; import org.hibernate.sql.results.graph.Initializer; @@ -75,15 +73,8 @@ public class EntityResultImpl extends AbstractEntityResultGraphNode return resultVariable; } - protected LockMode getLockMode(AssemblerCreationState creationState) { - return creationState.determineEffectiveLockMode( tableGroup.getSourceAlias() ); - } - - @Override - public DomainResultAssembler createResultAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createResultAssembler( (InitializerParent) parentAccess, creationState ); + protected String getSourceAlias() { + return tableGroup.getSourceAlias(); } @Override @@ -97,18 +88,18 @@ public class EntityResultImpl extends AbstractEntityResultGraphNode } @Override - public Initializer createInitializer( + public Initializer createInitializer( EntityResultImpl resultGraphNode, - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return resultGraphNode.createInitializer( parent, creationState ); } @Override - public Initializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { + public Initializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { return new EntityInitializerImpl( this, - getLockMode( creationState ), + getSourceAlias(), getIdentifierFetch(), getDiscriminatorFetch(), null, diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchByUniqueKeyInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchByUniqueKeyInitializer.java index fab3f700a5..b38ffc3dfd 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchByUniqueKeyInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchByUniqueKeyInitializer.java @@ -10,77 +10,61 @@ import org.hibernate.engine.spi.EntityUniqueKey; import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.log.LoggingHelper; -import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.spi.EntityIdentifierNavigablePath; import org.hibernate.spi.NavigablePath; -import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.graph.FetchParentAccess; -import org.hibernate.sql.results.graph.Initializer; +import org.hibernate.sql.results.graph.AssemblerCreationState; +import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.InitializerParent; -import org.hibernate.sql.results.jdbc.spi.RowProcessingState; /** * @author Andrea Boriero */ -public class EntitySelectFetchByUniqueKeyInitializer extends EntitySelectFetchInitializer { +public class EntitySelectFetchByUniqueKeyInitializer extends EntitySelectFetchInitializer { private final ToOneAttributeMapping fetchedAttribute; - /** - * @deprecated Use {@link #EntitySelectFetchByUniqueKeyInitializer(InitializerParent, ToOneAttributeMapping, NavigablePath, EntityPersister, DomainResultAssembler)} instead. - */ - @Deprecated(forRemoval = true) public EntitySelectFetchByUniqueKeyInitializer( - FetchParentAccess parentAccess, + InitializerParent parent, ToOneAttributeMapping fetchedAttribute, NavigablePath fetchedNavigable, EntityPersister concreteDescriptor, - DomainResultAssembler keyAssembler) { - this( (InitializerParent) parentAccess, fetchedAttribute, fetchedNavigable, concreteDescriptor, keyAssembler ); - } - - public EntitySelectFetchByUniqueKeyInitializer( - InitializerParent parent, - ToOneAttributeMapping fetchedAttribute, - NavigablePath fetchedNavigable, - EntityPersister concreteDescriptor, - DomainResultAssembler keyAssembler) { - super( parent, fetchedAttribute, fetchedNavigable, concreteDescriptor, keyAssembler ); + DomainResult keyResult, + AssemblerCreationState creationState) { + super( parent, fetchedAttribute, fetchedNavigable, concreteDescriptor, keyResult, creationState ); this.fetchedAttribute = fetchedAttribute; } @Override - protected void initialize(RowProcessingState rowProcessingState) { + protected void initialize(EntitySelectFetchInitializerData data) { final String entityName = concreteDescriptor.getEntityName(); final String uniqueKeyPropertyName = fetchedAttribute.getReferencedPropertyName(); - final SharedSessionContractImplementor session = rowProcessingState.getSession(); + final SharedSessionContractImplementor session = data.getRowProcessingState().getSession(); final EntityUniqueKey euk = new EntityUniqueKey( entityName, uniqueKeyPropertyName, - entityIdentifier, + data.entityIdentifier, concreteDescriptor.getPropertyType( uniqueKeyPropertyName ), session.getFactory() ); final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); - entityInstance = persistenceContext.getEntity( euk ); - if ( entityInstance == null ) { - entityInstance = concreteDescriptor.loadByUniqueKey( + data.setInstance( persistenceContext.getEntity( euk ) ); + if ( data.getInstance() == null ) { + data.setInstance( concreteDescriptor.loadByUniqueKey( uniqueKeyPropertyName, - entityIdentifier, + data.entityIdentifier, session - ); + ) ); // If the entity was not in the Persistence Context, but was found now, // add it to the Persistence Context - if ( entityInstance != null ) { - persistenceContext.addEntity( euk, entityInstance ); + if ( data.getInstance() != null ) { + persistenceContext.addEntity( euk, data.getInstance() ); } } - if ( entityInstance != null ) { - entityInstance = persistenceContext.proxyFor( entityInstance ); + if ( data.getInstance() != null ) { + data.setInstance( persistenceContext.proxyFor( data.getInstance() ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializer.java index a5e60f2c01..79981cc4b0 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializer.java @@ -23,12 +23,13 @@ import org.hibernate.persister.entity.EntityPersister; import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.LazyInitializer; import org.hibernate.spi.NavigablePath; +import org.hibernate.sql.results.graph.AssemblerCreationState; +import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Initializer; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.entity.EntityInitializer; -import org.hibernate.sql.results.graph.entity.EntityLoadingLogging; import org.hibernate.sql.results.graph.internal.AbstractInitializer; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; @@ -40,61 +41,57 @@ import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer; /** * @author Andrea Boriero */ -public class EntitySelectFetchInitializer extends AbstractInitializer implements EntityInitializer { +public class EntitySelectFetchInitializer + extends AbstractInitializer implements EntityInitializer { private static final String CONCRETE_NAME = EntitySelectFetchInitializer.class.getSimpleName(); - protected final InitializerParent parent; + protected final InitializerParent parent; private final NavigablePath navigablePath; private final boolean isPartOfKey; private final boolean isEnhancedForLazyLoading; protected final EntityPersister concreteDescriptor; protected final DomainResultAssembler keyAssembler; - private final ToOneAttributeMapping toOneMapping; + protected final ToOneAttributeMapping toOneMapping; - // per-row state - protected Object entityIdentifier; - protected Object entityInstance; + public static class EntitySelectFetchInitializerData extends InitializerData { + // per-row state + protected @Nullable Object entityIdentifier; + + public EntitySelectFetchInitializerData(RowProcessingState rowProcessingState) { + super( rowProcessingState ); + } - /** - * @deprecated Use {@link #EntitySelectFetchInitializer(InitializerParent, ToOneAttributeMapping, NavigablePath, EntityPersister, DomainResultAssembler)} instead. - */ - @Deprecated(forRemoval = true) - public EntitySelectFetchInitializer( - FetchParentAccess parent, - ToOneAttributeMapping toOneMapping, - NavigablePath fetchedNavigable, - EntityPersister concreteDescriptor, - DomainResultAssembler keyAssembler) { - this( (InitializerParent) parent, toOneMapping, fetchedNavigable, concreteDescriptor, keyAssembler ); } public EntitySelectFetchInitializer( - InitializerParent parent, + InitializerParent parent, ToOneAttributeMapping toOneMapping, NavigablePath fetchedNavigable, EntityPersister concreteDescriptor, - DomainResultAssembler keyAssembler) { + DomainResult keyResult, + AssemblerCreationState creationState) { + super( creationState ); this.parent = parent; this.toOneMapping = toOneMapping; this.navigablePath = fetchedNavigable; this.isPartOfKey = Initializer.isPartOfKey( fetchedNavigable, parent ); this.concreteDescriptor = concreteDescriptor; - this.keyAssembler = keyAssembler; + this.keyAssembler = keyResult.createResultAssembler( this, creationState ); this.isEnhancedForLazyLoading = concreteDescriptor.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading(); } + @Override + protected InitializerData createInitializerData(RowProcessingState rowProcessingState) { + return new EntitySelectFetchInitializerData( rowProcessingState ); + } + public ModelPart getInitializedPart(){ return toOneMapping; } @Override - public FetchParentAccess getFetchParentAccess() { - return (FetchParentAccess) parent; - } - - @Override - public @Nullable InitializerParent getParent() { + public @Nullable InitializerParent getParent() { return parent; } @@ -104,50 +101,52 @@ public class EntitySelectFetchInitializer extends AbstractInitializer implements } @Override - public void resolveInstance() { - if ( state != State.KEY_RESOLVED ) { + public void resolveInstance(Data data) { + if ( data.getState() != State.KEY_RESOLVED ) { return; } - entityIdentifier = keyAssembler.assemble( rowProcessingState ); + RowProcessingState rowProcessingState1 = data.getRowProcessingState(); + data.entityIdentifier = keyAssembler.assemble( rowProcessingState1 ); - if ( entityIdentifier == null ) { - state = State.MISSING; - entityInstance = null; + if ( data.entityIdentifier == null ) { + data.setState( State.MISSING ); + data.setInstance( null ); return; } - state = State.INITIALIZED; - initialize( rowProcessingState ); + data.setState( State.INITIALIZED ); + initialize( data ); } @Override - public void resolveInstance(Object instance) { + public void resolveInstance(Object instance, Data data) { if ( instance == null ) { - state = State.MISSING; - entityIdentifier = null; - entityInstance = null; + data.setState( State.MISSING ); + data.entityIdentifier = null; + data.setInstance( null ); } else { + final RowProcessingState rowProcessingState = data.getRowProcessingState(); final SharedSessionContractImplementor session = rowProcessingState.getSession(); - final LazyInitializer lazyInitializer = extractLazyInitializer( entityInstance ); + final LazyInitializer lazyInitializer = extractLazyInitializer( data.getInstance() ); if ( lazyInitializer == null ) { - state = State.INITIALIZED; - entityIdentifier = concreteDescriptor.getIdentifier( instance, session ); + data.setState( State.INITIALIZED ); + data.entityIdentifier = concreteDescriptor.getIdentifier( instance, session ); } else if ( lazyInitializer.isUninitialized() ) { - state = State.RESOLVED; - entityIdentifier = lazyInitializer.getIdentifier(); + data.setState( State.RESOLVED ); + data.entityIdentifier = lazyInitializer.getIdentifier(); } else { - state = State.INITIALIZED; - entityIdentifier = lazyInitializer.getIdentifier(); + data.setState( State.INITIALIZED ); + data.entityIdentifier = lazyInitializer.getIdentifier(); } - entityInstance = instance; - final Initializer initializer = keyAssembler.getInitializer(); + data.setInstance( instance ); + final Initializer initializer = keyAssembler.getInitializer(); if ( initializer != null ) { - initializer.resolveInstance( entityIdentifier ); + initializer.resolveInstance( data.entityIdentifier, rowProcessingState ); } - else if ( !rowProcessingState.isQueryCacheHit() && rowProcessingState.getQueryOptions().isResultCachingEnabled() == Boolean.TRUE ) { + else if ( rowProcessingState.needsResolveState() ) { // Resolve the state of the identifier if result caching is enabled and this is not a query cache hit keyAssembler.resolveState( rowProcessingState ); } @@ -155,129 +154,95 @@ public class EntitySelectFetchInitializer extends AbstractInitializer implements } @Override - public void initializeInstance() { - if ( state != State.RESOLVED ) { + public void initializeInstance(Data data) { + if ( data.getState() != State.RESOLVED ) { return; } - state = State.INITIALIZED; - Hibernate.initialize( entityInstance ); + data.setState( State.INITIALIZED ); + Hibernate.initialize( data.getInstance() ); } - protected void initialize(RowProcessingState rowProcessingState) { + protected void initialize(EntitySelectFetchInitializerData data) { + final RowProcessingState rowProcessingState = data.getRowProcessingState(); final SharedSessionContractImplementor session = rowProcessingState.getSession(); - final EntityKey entityKey = new EntityKey( entityIdentifier, concreteDescriptor ); + final EntityKey entityKey = new EntityKey( data.entityIdentifier, concreteDescriptor ); final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); final EntityHolder holder = persistenceContext.getEntityHolder( entityKey ); if ( holder != null ) { - if ( EntityLoadingLogging.ENTITY_LOADING_LOGGER.isDebugEnabled() ) { - EntityLoadingLogging.ENTITY_LOADING_LOGGER.debugf( - "(%s) Found existing loading entry [%s] - using loading instance", - CONCRETE_NAME, - toLoggableString( - getNavigablePath(), - entityIdentifier - ) - ); - } - entityInstance = persistenceContext.proxyFor( holder, concreteDescriptor ); + data.setInstance( persistenceContext.proxyFor( holder, concreteDescriptor ) ); if ( holder.getEntityInitializer() == null ) { - if ( entityInstance != null && Hibernate.isInitialized( entityInstance ) ) { - state = State.INITIALIZED; + if ( data.getInstance() != null && Hibernate.isInitialized( data.getInstance() ) ) { + data.setState( State.INITIALIZED ); return; } } else if ( holder.getEntityInitializer() != this ) { // the entity is already being loaded elsewhere - if ( EntityLoadingLogging.ENTITY_LOADING_LOGGER.isDebugEnabled() ) { - EntityLoadingLogging.ENTITY_LOADING_LOGGER.debugf( - "(%s) Entity [%s] being loaded by another initializer [%s] - skipping processing", - CONCRETE_NAME, - toLoggableString( getNavigablePath(), entityIdentifier ), - holder.getEntityInitializer() - ); - } - state = State.INITIALIZED; + data.setState( State.INITIALIZED ); return; } - else if ( entityInstance == null ) { + else if ( data.getInstance() == null ) { // todo: maybe mark this as resolved instead? assert holder.getProxy() == null : "How to handle this case?"; - state = State.INITIALIZED; + data.setState( State.INITIALIZED ); return; } } - state = State.INITIALIZED; + data.setState( State.INITIALIZED ); final String entityName = concreteDescriptor.getEntityName(); - if ( EntityLoadingLogging.ENTITY_LOADING_LOGGER.isDebugEnabled() ) { - EntityLoadingLogging.ENTITY_LOADING_LOGGER.debugf( - "(%s) Invoking session#internalLoad for entity (%s) : %s", - CONCRETE_NAME, - toLoggableString( getNavigablePath(), entityIdentifier ), - entityIdentifier - ); - } - entityInstance = session.internalLoad( + data.setInstance( session.internalLoad( entityName, - entityIdentifier, + data.entityIdentifier, true, toOneMapping.isInternalLoadNullable() - ); + ) ); - if ( entityInstance == null ) { + if ( data.getInstance() == null ) { if ( toOneMapping.getNotFoundAction() == NotFoundAction.EXCEPTION ) { - throw new FetchNotFoundException( entityName, entityIdentifier ); + throw new FetchNotFoundException( entityName, data.entityIdentifier ); } rowProcessingState.getSession().getPersistenceContextInternal().claimEntityHolderIfPossible( - new EntityKey( entityIdentifier, concreteDescriptor ), - entityInstance, + new EntityKey( data.entityIdentifier, concreteDescriptor ), + data.getInstance(), rowProcessingState.getJdbcValuesSourceProcessingState(), this ); } - if ( EntityLoadingLogging.ENTITY_LOADING_LOGGER.isDebugEnabled() ) { - EntityLoadingLogging.ENTITY_LOADING_LOGGER.debugf( - "(%s) Entity [%s] : %s has being loaded by session.internalLoad.", - CONCRETE_NAME, - toLoggableString( getNavigablePath(), entityIdentifier ), - entityIdentifier - ); - } - final boolean unwrapProxy = toOneMapping.isUnwrapProxy() && isEnhancedForLazyLoading; - final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entityInstance ); + final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( data.getInstance() ); if ( lazyInitializer != null ) { lazyInitializer.setUnwrap( unwrapProxy ); } } @Override - public void initializeInstanceFromParent(Object parentInstance) { + public void initializeInstanceFromParent(Object parentInstance, Data data) { final AttributeMapping attributeMapping = getInitializedPart().asAttributeMapping(); final Object instance = attributeMapping != null ? attributeMapping.getValue( parentInstance ) : parentInstance; if ( instance == null ) { - state = State.MISSING; - entityIdentifier = null; - entityInstance = null; + data.setState( State.MISSING ); + data.entityIdentifier = null; + data.setInstance( null ); } else { - state = State.INITIALIZED; + data.setState( State.INITIALIZED ); // No need to initialize this - entityIdentifier = null; - entityInstance = instance; + data.entityIdentifier = null; + data.setInstance( instance ); Hibernate.initialize( instance ); } } @Override - protected void forEachSubInitializer(BiConsumer consumer, X arg) { - final Initializer initializer = keyAssembler.getInitializer(); + protected void forEachSubInitializer(BiConsumer, RowProcessingState> consumer, InitializerData data) { + final Initializer initializer = keyAssembler.getInitializer(); if ( initializer != null ) { - consumer.accept( initializer, arg ); + consumer.accept( initializer, data.getRowProcessingState() ); } } @@ -287,20 +252,20 @@ public class EntitySelectFetchInitializer extends AbstractInitializer implements } @Override - public Object getEntityInstance() { - return entityInstance; + public Object getEntityInstance(Data data) { + return data.getInstance(); } @Override - public boolean isEntityInitialized() { - return state == State.INITIALIZED; - } - - @Override - public EntityPersister getConcreteDescriptor() { + public EntityPersister getConcreteDescriptor(Data data) { return concreteDescriptor; } + @Override + public @Nullable Object getEntityIdentifier(Data data) { + return data.entityIdentifier; + } + @Override public boolean isPartOfKey() { return isPartOfKey; @@ -316,15 +281,4 @@ public class EntitySelectFetchInitializer extends AbstractInitializer implements return "EntitySelectFetchInitializer(" + LoggingHelper.toLoggableString( getNavigablePath() ) + ")"; } - @Override - public EntityKey getEntityKey() { - throw new UnsupportedOperationException( - "This should never happen, because this initializer has not child initializers" ); - } - - @Override - public Object getParentKey() { - throw new UnsupportedOperationException( - "This should never happen, because this initializer has not child initializers" ); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializerBuilder.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializerBuilder.java index 7ec19f5778..866e625495 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializerBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntitySelectFetchInitializerBuilder.java @@ -15,8 +15,6 @@ import org.hibernate.persister.entity.EntityPersister; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; -import org.hibernate.sql.results.graph.FetchParentAccess; -import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.embeddable.EmbeddableInitializer; import org.hibernate.sql.results.graph.entity.EntityInitializer; @@ -27,26 +25,8 @@ import static org.hibernate.sql.results.graph.entity.internal.EntitySelectFetchI public class EntitySelectFetchInitializerBuilder { - public static EntityInitializer createInitializer( - FetchParentAccess parentAccess, - ToOneAttributeMapping fetchedAttribute, - EntityPersister entityPersister, - DomainResult keyResult, - NavigablePath navigablePath, - boolean selectByUniqueKey, - AssemblerCreationState creationState) { - return createInitializer( - (InitializerParent) parentAccess, - fetchedAttribute, - entityPersister, - keyResult, - navigablePath, - selectByUniqueKey, - creationState - ); - } - public static EntityInitializer createInitializer( - InitializerParent parent, + public static EntityInitializer createInitializer( + InitializerParent parent, ToOneAttributeMapping fetchedAttribute, EntityPersister entityPersister, DomainResult keyResult, @@ -59,28 +39,31 @@ public class EntitySelectFetchInitializerBuilder { fetchedAttribute, navigablePath, entityPersister, - keyResult.createResultAssembler( parent, creationState ) + keyResult, + creationState ); } if ( !parent.isEntityInitializer() && parent.findOwningEntityInitializer() == null ) { // Batch initializers require an owning parent initializer - return new EntitySelectFetchInitializer( + return new EntitySelectFetchInitializer<>( parent, fetchedAttribute, navigablePath, entityPersister, - keyResult.createResultAssembler( parent, creationState ) + keyResult, + creationState ); } final BatchMode batchMode = determineBatchMode( entityPersister, parent, creationState ); switch ( batchMode ) { case NONE: - return new EntitySelectFetchInitializer( + return new EntitySelectFetchInitializer<>( parent, fetchedAttribute, navigablePath, entityPersister, - keyResult.createResultAssembler( parent, creationState ) + keyResult, + creationState ); case BATCH_LOAD: if ( parent.isEmbeddableInitializer() ) { @@ -89,7 +72,8 @@ public class EntitySelectFetchInitializerBuilder { fetchedAttribute, navigablePath, entityPersister, - keyResult.createResultAssembler( parent, creationState ) + keyResult, + creationState ); } else { @@ -98,7 +82,8 @@ public class EntitySelectFetchInitializerBuilder { fetchedAttribute, navigablePath, entityPersister, - keyResult.createResultAssembler( parent, creationState ) + keyResult, + creationState ); } case BATCH_INITIALIZE: @@ -107,7 +92,8 @@ public class EntitySelectFetchInitializerBuilder { fetchedAttribute, navigablePath, entityPersister, - keyResult.createResultAssembler( parent, creationState ) + keyResult, + creationState ); } throw new IllegalStateException( "Should be unreachable" ); @@ -115,23 +101,19 @@ public class EntitySelectFetchInitializerBuilder { private static BatchMode determineBatchMode( EntityPersister entityPersister, - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { - if ( creationState.isScrollResult() - || !creationState.getExecutionContext() - .getSession() - .getLoadQueryInfluencers() - .effectivelyBatchLoadable( entityPersister ) ) { + if ( !entityPersister.isBatchLoadable() ) { return NONE; } - else if ( creationState.isDynamicInstantiation() ) { + if ( creationState.isDynamicInstantiation() ) { if ( canBatchInitializeBeUsed( entityPersister ) ) { return BatchMode.BATCH_INITIALIZE; } return NONE; } while ( parent.isEmbeddableInitializer() ) { - final EmbeddableInitializer embeddableInitializer = parent.asEmbeddableInitializer(); + final EmbeddableInitializer embeddableInitializer = parent.asEmbeddableInitializer(); final EmbeddableValuedModelPart initializedPart = embeddableInitializer.getInitializedPart(); // For entity identifier mappings we can't batch load, // because the entity identifier needs the instance in the resolveKey phase, @@ -139,6 +121,7 @@ public class EntitySelectFetchInitializerBuilder { if ( initializedPart.isEntityIdentifierMapping() // todo: check if the virtual check is necessary || initializedPart.isVirtual() + || initializedPart.getMappedType().isPolymorphic() // If the parent embeddable has a custom instantiator, // we can't inject entities later through setValues() || !( initializedPart.getMappedType().getRepresentationStrategy().getInstantiator() diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/ArgumentDomainResult.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/ArgumentDomainResult.java index f6d178d79e..1c98d5bc7f 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/ArgumentDomainResult.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/ArgumentDomainResult.java @@ -10,7 +10,6 @@ import java.util.BitSet; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.type.descriptor.java.JavaType; @@ -41,14 +40,7 @@ public class ArgumentDomainResult implements DomainResult { } @Override - public ArgumentReader createResultAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createResultAssembler( (InitializerParent) parentAccess, creationState ); - } - - @Override - public ArgumentReader createResultAssembler(InitializerParent parent, AssemblerCreationState creationState) { + public ArgumentReader createResultAssembler(InitializerParent parent, AssemblerCreationState creationState) { return new ArgumentReader<>( realDomainResult.createResultAssembler( parent, creationState ), getResultVariable() diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/ArgumentReader.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/ArgumentReader.java index af255967c6..24b0e55f11 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/ArgumentReader.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/ArgumentReader.java @@ -10,7 +10,6 @@ import java.util.function.BiConsumer; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Initializer; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.descriptor.java.JavaType; @@ -36,8 +35,8 @@ public class ArgumentReader implements DomainResultAssembler { } @Override - public A assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) { - return delegateAssembler.assemble( rowProcessingState, options ); + public @Nullable A assemble(RowProcessingState rowProcessingState) { + return delegateAssembler.assemble( rowProcessingState ); } @Override @@ -45,23 +44,18 @@ public class ArgumentReader implements DomainResultAssembler { return delegateAssembler.getAssembledJavaType(); } - @Override - public @Nullable A assemble(RowProcessingState rowProcessingState) { - return delegateAssembler.assemble( rowProcessingState ); - } - @Override public void resolveState(RowProcessingState rowProcessingState) { delegateAssembler.resolveState( rowProcessingState ); } @Override - public @Nullable Initializer getInitializer() { + public @Nullable Initializer getInitializer() { return delegateAssembler.getInitializer(); } @Override - public void forEachResultAssembler(BiConsumer consumer, X arg) { + public void forEachResultAssembler(BiConsumer, X> consumer, X arg) { delegateAssembler.forEachResultAssembler( consumer, arg ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationAssemblerConstructorImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationAssemblerConstructorImpl.java index 081b3be560..f945b0c54d 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationAssemblerConstructorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationAssemblerConstructorImpl.java @@ -8,13 +8,13 @@ package org.hibernate.sql.results.graph.instantiation.internal; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; import java.util.List; import java.util.function.BiConsumer; import org.hibernate.query.sqm.sql.internal.InstantiationException; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Initializer; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.descriptor.java.JavaType; @@ -41,11 +41,11 @@ public class DynamicInstantiationAssemblerConstructorImpl implements DomainRe } @Override - public R assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) { + public R assemble(RowProcessingState rowProcessingState) { final int numberOfArgs = argumentReaders.size(); Object[] args = new Object[ numberOfArgs ]; for ( int i = 0; i < numberOfArgs; i++ ) { - args[i] = argumentReaders.get( i ).assemble( rowProcessingState, options ); + args[i] = argumentReaders.get( i ).assemble( rowProcessingState ); } try { @@ -62,7 +62,7 @@ public class DynamicInstantiationAssemblerConstructorImpl implements DomainRe } @Override - public void forEachResultAssembler(BiConsumer consumer, X arg) { + public void forEachResultAssembler(BiConsumer, X> consumer, X arg) { for ( ArgumentReader argumentReader : argumentReaders ) { argumentReader.forEachResultAssembler( consumer, arg ); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationAssemblerInjectionImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationAssemblerInjectionImpl.java index 3d18283446..92b151e4ff 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationAssemblerInjectionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationAssemblerInjectionImpl.java @@ -20,7 +20,6 @@ import org.hibernate.internal.util.beans.BeanInfoHelper; import org.hibernate.query.sqm.sql.internal.InstantiationException; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Initializer; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.descriptor.java.JavaType; @@ -32,14 +31,14 @@ import static org.hibernate.sql.results.graph.instantiation.internal.Instantiati */ public class DynamicInstantiationAssemblerInjectionImpl implements DomainResultAssembler { private final JavaType target; - private final List beanInjections = new ArrayList<>(); + private final List beanInjections; public DynamicInstantiationAssemblerInjectionImpl( JavaType target, List> argumentReaders) { this.target = target; final Class targetJavaType = target.getJavaTypeClass(); - + final List beanInjections = new ArrayList<>( argumentReaders.size() ); BeanInfoHelper.visitBeanInfo( targetJavaType, beanInfo -> { @@ -52,6 +51,12 @@ public class DynamicInstantiationAssemblerInjectionImpl implements DomainResu if ( argumentReaders.size() != beanInjections.size() ) { throw new IllegalStateException( "The number of readers did not match the number of injections" ); } + this.beanInjections = beanInjections; + } + + private DynamicInstantiationAssemblerInjectionImpl(List beanInjections, JavaType target) { + this.target = target; + this.beanInjections = beanInjections; } private static BeanInjection injection(BeanInfo beanInfo, ArgumentReader argument, Class targetJavaType) { @@ -86,7 +91,7 @@ public class DynamicInstantiationAssemblerInjectionImpl implements DomainResu @Override @SuppressWarnings("unchecked") - public T assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) { + public T assemble(RowProcessingState rowProcessingState) { final T result; try { final Constructor constructor = target.getJavaTypeClass().getDeclaredConstructor(); @@ -99,14 +104,14 @@ public class DynamicInstantiationAssemblerInjectionImpl implements DomainResu + target.getTypeName() + "' using default constructor: " + e.getMessage(), e ); } for ( BeanInjection beanInjection : beanInjections ) { - final Object assembled = beanInjection.getValueAssembler().assemble( rowProcessingState, options ); + final Object assembled = beanInjection.getValueAssembler().assemble( rowProcessingState ); beanInjection.getBeanInjector().inject( result, assembled ); } return result; } @Override - public void forEachResultAssembler(BiConsumer consumer, X arg) { + public void forEachResultAssembler(BiConsumer, X> consumer, X arg) { for ( BeanInjection beanInjection : beanInjections ) { beanInjection.getValueAssembler().forEachResultAssembler( consumer, arg ); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationAssemblerListImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationAssemblerListImpl.java index 51b74d5247..9e8d94e152 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationAssemblerListImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationAssemblerListImpl.java @@ -12,7 +12,6 @@ import java.util.function.BiConsumer; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Initializer; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.descriptor.java.JavaType; @@ -42,17 +41,16 @@ public class DynamicInstantiationAssemblerListImpl implements DomainResultAssemb @Override public List assemble( - RowProcessingState rowProcessingState, - JdbcValuesSourceProcessingOptions options) { + RowProcessingState rowProcessingState) { final ArrayList result = new ArrayList<>(); for ( ArgumentReader argumentReader : argumentReaders ) { - result.add( argumentReader.assemble( rowProcessingState, options ) ); + result.add( argumentReader.assemble( rowProcessingState ) ); } return result; } @Override - public void forEachResultAssembler(BiConsumer consumer, X arg) { + public void forEachResultAssembler(BiConsumer, X> consumer, X arg) { for ( ArgumentReader argumentReader : argumentReaders ) { argumentReader.forEachResultAssembler( consumer, arg ); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationAssemblerMapImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationAssemblerMapImpl.java index 6f529b521d..8e50131a30 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationAssemblerMapImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationAssemblerMapImpl.java @@ -7,6 +7,7 @@ package org.hibernate.sql.results.graph.instantiation.internal; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -16,7 +17,6 @@ import java.util.function.BiConsumer; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Initializer; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.descriptor.java.JavaType; @@ -46,7 +46,13 @@ public class DynamicInstantiationAssemblerMapImpl implements DomainResultAssembl throw new IllegalStateException( "Encountered duplicate alias for Map dynamic instantiation argument [" + argumentReader.getAlias() + "]" ); } } + } + private DynamicInstantiationAssemblerMapImpl( + List> argumentReaders, + JavaType> mapJavaType) { + this.mapJavaType = mapJavaType; + this.argumentReaders = argumentReaders; } @Override @@ -56,14 +62,13 @@ public class DynamicInstantiationAssemblerMapImpl implements DomainResultAssembl @Override public Map assemble( - RowProcessingState rowProcessingState, - JdbcValuesSourceProcessingOptions options) { + RowProcessingState rowProcessingState) { final HashMap result = new HashMap<>(); for ( ArgumentReader argumentReader : argumentReaders ) { result.put( argumentReader.getAlias(), - argumentReader.assemble( rowProcessingState, options ) + argumentReader.assemble( rowProcessingState ) ); } @@ -71,7 +76,7 @@ public class DynamicInstantiationAssemblerMapImpl implements DomainResultAssembl } @Override - public void forEachResultAssembler(BiConsumer consumer, X arg) { + public void forEachResultAssembler(BiConsumer, X> consumer, X arg) { for ( ArgumentReader argumentReader : argumentReaders ) { argumentReader.forEachResultAssembler( consumer, arg ); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationResultImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationResultImpl.java index 84e40a4645..22979c5988 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationResultImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationResultImpl.java @@ -18,7 +18,6 @@ import org.hibernate.internal.util.StringHelper; import org.hibernate.query.sqm.DynamicInstantiationNature; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.instantiation.DynamicInstantiationResult; import org.hibernate.type.descriptor.java.JavaType; @@ -83,14 +82,7 @@ public class DynamicInstantiationResultImpl implements DynamicInstantiationRe } @Override - public DomainResultAssembler createResultAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createResultAssembler( (InitializerParent) parentAccess, creationState ); - } - - @Override - public DomainResultAssembler createResultAssembler(InitializerParent parent, AssemblerCreationState creationState) { + public DomainResultAssembler createResultAssembler(InitializerParent parent, AssemblerCreationState creationState) { boolean areAllArgumentsAliased = true; boolean areAnyArgumentsAliased = false; final Set aliases = new HashSet<>(); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/internal/AbstractInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/internal/AbstractInitializer.java index 6b922e32cf..0e98006db3 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/internal/AbstractInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/internal/AbstractInitializer.java @@ -8,47 +8,51 @@ package org.hibernate.sql.results.graph.internal; import java.util.function.BiConsumer; -import org.hibernate.sql.exec.spi.ExecutionContext; +import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.Initializer; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; -public abstract class AbstractInitializer implements Initializer { +public abstract class AbstractInitializer implements Initializer { - protected RowProcessingState rowProcessingState; - protected State state = State.UNINITIALIZED; + protected final int initializerId; + + protected AbstractInitializer(AssemblerCreationState creationState) { + this.initializerId = creationState.acquireInitializerId(); + } @Override public void startLoading(RowProcessingState rowProcessingState) { - this.rowProcessingState = rowProcessingState; - forEachSubInitializer( Initializer::startLoading, rowProcessingState ); + final InitializerData data = createInitializerData( rowProcessingState ); + rowProcessingState.setInitializerData( initializerId, data ); + forEachSubInitializer( Initializer::startLoading, data ); + } + + protected abstract InitializerData createInitializerData(RowProcessingState rowProcessingState); + + @Override + public void resolveKey(Data data) { + data.setState( State.KEY_RESOLVED ); + forEachSubInitializer( Initializer::resolveKey, data ); } @Override - public void endLoading(ExecutionContext executionContext) { - rowProcessingState = null; - } - - @Override - public void resolveKey() { - state = State.KEY_RESOLVED; - forEachSubInitializer( (initializer, processingState) -> initializer.resolveKey(), rowProcessingState ); - } - - @Override - public void initializeInstance() { + public void initializeInstance(Data data) { // No-op by default } @Override - public State getState() { - return state; + public Data getData(RowProcessingState rowProcessingState) { + return rowProcessingState.getInitializerData( initializerId ); } @Override - public void finishUpRow() { - state = State.UNINITIALIZED; + public void finishUpRow(Data data) { + data.setState( Initializer.State.UNINITIALIZED ); } - protected abstract void forEachSubInitializer(BiConsumer consumer, X arg); + protected abstract void forEachSubInitializer( + BiConsumer, RowProcessingState> consumer, + InitializerData data); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/tuple/TupleResult.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/tuple/TupleResult.java index 02d31df29a..6dd34d97b9 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/tuple/TupleResult.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/tuple/TupleResult.java @@ -13,7 +13,6 @@ import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.basic.BasicResultGraphNode; import org.hibernate.type.descriptor.java.JavaType; @@ -74,14 +73,7 @@ public class TupleResult implements DomainResult, BasicResultGraphNode @Override public DomainResultAssembler createResultAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createResultAssembler( (InitializerParent) parentAccess, creationState ); - } - - @Override - public DomainResultAssembler createResultAssembler( - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return assembler; } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/tuple/TupleResultAssembler.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/tuple/TupleResultAssembler.java index 036d27dae7..d6c880561c 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/tuple/TupleResultAssembler.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/tuple/TupleResultAssembler.java @@ -8,7 +8,6 @@ package org.hibernate.sql.results.graph.tuple; import org.hibernate.sql.results.ResultsLogger; import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.descriptor.java.JavaType; @@ -44,8 +43,7 @@ public class TupleResultAssembler implements DomainResultAssembler { @Override public J assemble( - RowProcessingState rowProcessingState, - JdbcValuesSourceProcessingOptions options) { + RowProcessingState rowProcessingState) { final Object[] jdbcValues = extractRawValue( rowProcessingState ); if ( ResultsLogger.RESULTS_MESSAGE_LOGGER.isDebugEnabled() ) { diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/InitializersList.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/InitializersList.java index ec5ef5a811..e552955969 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/InitializersList.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/InitializersList.java @@ -10,9 +10,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl; +import org.hibernate.sql.results.jdbc.spi.RowProcessingState; /** * Internal helper to keep track of the various @@ -26,61 +26,50 @@ import org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl; */ public final class InitializersList { - private final Initializer[] initializers; - private final Initializer[] sortedForResolveInstance; + private final Initializer[] initializers; + private final Initializer[] sortedForResolveInstance; private final boolean hasCollectionInitializers; private InitializersList( - Initializer[] initializers, - Initializer[] sortedForResolveInstance, + Initializer[] initializers, + Initializer[] sortedForResolveInstance, boolean hasCollectionInitializers) { this.initializers = initializers; this.sortedForResolveInstance = sortedForResolveInstance; this.hasCollectionInitializers = hasCollectionInitializers; } + public Initializer[] getInitializers() { + return initializers; + } + + public Initializer[] getSortedForResolveInstance() { + return sortedForResolveInstance; + } + @Deprecated //for simpler migration to the new SPI - public List asList() { + public List> asList() { return Arrays.asList( initializers ); } - - public void finishUpRow() { - for ( Initializer init : initializers ) { - init.finishUpRow(); - } + public int size() { + return initializers.length; } - public void initializeInstance() { - for ( Initializer init : initializers ) { - init.initializeInstance(); - } - } - - public void endLoading(final ExecutionContext executionContext) { - for ( Initializer initializer : initializers ) { - initializer.endLoading( executionContext ); - } - } - - public void resolveInstances() { - for ( Initializer init : sortedForResolveInstance ) { - init.resolveInstance(); - } - } - - public boolean hasCollectionInitializers() { - return this.hasCollectionInitializers; - } - - static class Builder { - private ArrayList initializers = new ArrayList<>(); + public static class Builder { + private final ArrayList> initializers; int nonCollectionInitializersNum = 0; int resolveFirstNum = 0; - public Builder() {} + public Builder() { + initializers = new ArrayList<>(); + } - public void addInitializer(final Initializer initializer) { + public Builder(int size) { + initializers = new ArrayList<>( size ); + } + + public void addInitializer(final Initializer initializer) { initializers.add( initializer ); //in this method we perform these checks merely to learn the sizing hints, //so to not need dynamically scaling collections. @@ -95,17 +84,17 @@ public final class InitializersList { } } - private static boolean initializeFirst(final Initializer initializer) { + private static boolean initializeFirst(final Initializer initializer) { return initializer instanceof EntityInitializerImpl; } - InitializersList build() { + public InitializersList build() { final int size = initializers.size(); - final Initializer[] sortedForResolveInstance = new Initializer[size]; + final Initializer[] sortedForResolveInstance = new Initializer[size]; int resolveFirstIdx = 0; int resolveLaterIdx = resolveFirstNum; - final Initializer[] originalSortInitializers = toArray( initializers ); - for ( Initializer initializer : originalSortInitializers ) { + final Initializer[] originalSortInitializers = toArray( initializers ); + for ( Initializer initializer : originalSortInitializers ) { if ( initializeFirst( initializer ) ) { sortedForResolveInstance[resolveFirstIdx++] = initializer; } @@ -121,8 +110,8 @@ public final class InitializersList { ); } - private Initializer[] toArray(final ArrayList initializers) { - return initializers.toArray( new Initializer[initializers.size()] ); + private Initializer[] toArray(final ArrayList> initializers) { + return initializers.toArray( new Initializer[initializers.size()] ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/LoadingCollectionEntryImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/LoadingCollectionEntryImpl.java index 443318e34c..0257fe4bd8 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/LoadingCollectionEntryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/LoadingCollectionEntryImpl.java @@ -25,14 +25,14 @@ import org.hibernate.sql.results.graph.collection.LoadingCollectionEntry; */ public class LoadingCollectionEntryImpl implements LoadingCollectionEntry { private final CollectionPersister collectionDescriptor; - private final CollectionInitializer initializer; + private final CollectionInitializer initializer; private final Object key; private final PersistentCollection collectionInstance; private final List loadingState = new ArrayList<>(); public LoadingCollectionEntryImpl( CollectionPersister collectionDescriptor, - CollectionInitializer initializer, + CollectionInitializer initializer, Object key, PersistentCollection collectionInstance) { this.collectionDescriptor = collectionDescriptor; @@ -51,7 +51,7 @@ public class LoadingCollectionEntryImpl implements LoadingCollectionEntry { /** * Access to the initializer that is responsible for initializing this collection */ - @Override public CollectionInitializer getInitializer() { + @Override public CollectionInitializer getInitializer() { return initializer; } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/NavigablePathMapToInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/NavigablePathMapToInitializer.java index b9f500b197..34e2548f79 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/NavigablePathMapToInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/NavigablePathMapToInitializer.java @@ -28,7 +28,7 @@ public final class NavigablePathMapToInitializer { private HashMap map = null; - public Initializer get(final NavigablePath navigablePath) { + public Initializer get(final NavigablePath navigablePath) { if ( map != null && navigablePath != null ) { final InitializerHolder h = map.get( navigablePath ); if ( h != null ) { @@ -38,7 +38,7 @@ public final class NavigablePathMapToInitializer { return null; } - public void put(final NavigablePath navigablePath, final Initializer initializer) { + public void put(final NavigablePath navigablePath, final Initializer initializer) { Objects.requireNonNull( navigablePath ); Objects.requireNonNull( initializer ); if ( map == null ) { @@ -61,7 +61,7 @@ public final class NavigablePathMapToInitializer { final StringBuilder sb = new StringBuilder( "Initializer list:\n" ); for ( Map.Entry holderEntry : map.entrySet() ) { final NavigablePath navigablePath = holderEntry.getKey(); - final Initializer initializer = holderEntry.getValue().initializer; + final Initializer initializer = holderEntry.getValue().initializer; String formatted = String.format( " %s -> %s@%s (%s)", navigablePath, @@ -80,9 +80,9 @@ public final class NavigablePathMapToInitializer { //Custom holder to avoid type pollution: //we make the type explicit, and this is a concrete class. private static final class InitializerHolder { - final Initializer initializer; + final Initializer initializer; - private InitializerHolder(final Initializer init) { + private InitializerHolder(final Initializer init) { this.initializer = init; } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/NullValueAssembler.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/NullValueAssembler.java index 08fc15e78b..12dac6b0ae 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/NullValueAssembler.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/NullValueAssembler.java @@ -7,7 +7,6 @@ package org.hibernate.sql.results.internal; import org.hibernate.sql.results.graph.DomainResultAssembler; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.descriptor.java.JavaType; @@ -22,7 +21,7 @@ public class NullValueAssembler implements DomainResultAssembler { } @Override - public J assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) { + public J assemble(RowProcessingState rowProcessingState) { return null; } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/ResultsHelper.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/ResultsHelper.java index e7672ee719..41f984c3c2 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/ResultsHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/ResultsHelper.java @@ -10,8 +10,6 @@ import java.util.List; import java.util.function.Supplier; import org.hibernate.CacheMode; -import org.hibernate.LockMode; -import org.hibernate.LockOptions; import org.hibernate.cache.spi.access.CollectionDataAccess; import org.hibernate.cache.spi.entry.CollectionCacheEntry; import org.hibernate.collection.spi.PersistentCollection; @@ -44,8 +42,10 @@ import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.InitializerProducer; import org.hibernate.sql.results.graph.collection.internal.AbstractImmediateCollectionInitializer; import org.hibernate.sql.results.graph.instantiation.DynamicInstantiationResult; +import org.hibernate.sql.results.jdbc.internal.StandardJdbcValuesMapping; import org.hibernate.sql.results.jdbc.spi.JdbcValues; import org.hibernate.sql.results.jdbc.spi.JdbcValuesMapping; +import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingResolution; import org.hibernate.sql.results.spi.RowReader; import org.hibernate.sql.results.spi.RowTransformer; import org.hibernate.stat.spi.StatisticsImplementor; @@ -58,33 +58,21 @@ public class ResultsHelper { private static final CoreMessageLogger LOG = CoreLogging.messageLogger( ResultsHelper.class ); public static RowReader createRowReader( - ExecutionContext executionContext, - LockOptions lockOptions, + SessionFactoryImplementor sessionFactory, RowTransformer rowTransformer, Class transformedResultJavaType, JdbcValues jdbcValues) { - return createRowReader( executionContext, lockOptions, rowTransformer, transformedResultJavaType, jdbcValues.getValuesMapping()); + return createRowReader( sessionFactory, rowTransformer, transformedResultJavaType, jdbcValues.getValuesMapping() ); } public static RowReader createRowReader( - ExecutionContext executionContext, - LockOptions lockOptions, + SessionFactoryImplementor sessionFactory, RowTransformer rowTransformer, Class transformedResultJavaType, JdbcValuesMapping jdbcValuesMapping) { - final AssemblerCreationStateImpl creationState = new AssemblerCreationStateImpl( - executionContext, - jdbcValuesMapping, - lockOptions - ); - - final List> assemblers = jdbcValuesMapping.resolveAssemblers( creationState ); - creationState.initializerMap.logInitializers(); - + final JdbcValuesMappingResolution jdbcValuesMappingResolution = jdbcValuesMapping.resolveAssemblers( sessionFactory ); return new StandardRowReader<>( - assemblers, - creationState.hasCollectionInitializers, - creationState.initializerListBuilder.build(), + jdbcValuesMappingResolution, rowTransformer, transformedResultJavaType ); @@ -265,117 +253,4 @@ public class ResultsHelper { } } } - - private static class AssemblerCreationStateImpl implements AssemblerCreationState { - private final ExecutionContext executionContext; - private final JdbcValuesMapping jdbcValuesMapping; - private final LockOptions lockOptions; - private final SessionFactoryImplementor sessionFactory; - //custom Map - private final NavigablePathMapToInitializer initializerMap = new NavigablePathMapToInitializer(); - private final InitializersList.Builder initializerListBuilder = new InitializersList.Builder(); - boolean hasCollectionInitializers; - Boolean dynamicInstantiation; - - public AssemblerCreationStateImpl( - ExecutionContext executionContext, - JdbcValuesMapping jdbcValuesMapping, - LockOptions lockOptions) { - this.executionContext = executionContext; - this.jdbcValuesMapping = jdbcValuesMapping; - this.lockOptions = lockOptions; - this.sessionFactory = executionContext.getSession().getFactory(); - } - - @Override - public boolean isScrollResult() { - return executionContext.isScrollResult(); - } - - @Override - public boolean isDynamicInstantiation() { - if ( dynamicInstantiation == null ) { - dynamicInstantiation = jdbcValuesMapping.getDomainResults() - .stream() - .anyMatch( domainResult -> domainResult instanceof DynamicInstantiationResult ); - } - return dynamicInstantiation; - } - - @Override - public LockMode determineEffectiveLockMode(String identificationVariable) { - return lockOptions.getEffectiveLockMode( identificationVariable ); - } - - @Override - public Initializer resolveInitializer( - NavigablePath navigablePath, - ModelPart fetchedModelPart, - Supplier producer) { - return resolveInitializer( - navigablePath, - fetchedModelPart, - null, - null, - (resultGraphNode, parent, creationState) -> producer.get() - ); - } - - @Override - public

Initializer resolveInitializer( - P resultGraphNode, - InitializerParent parent, - InitializerProducer

producer) { - return resolveInitializer( - resultGraphNode.getNavigablePath(), - resultGraphNode.getReferencedModePart(), - resultGraphNode, - parent, - producer - ); - } - - public Initializer resolveInitializer( - NavigablePath navigablePath, - ModelPart fetchedModelPart, - T resultGraphNode, - InitializerParent parent, - InitializerProducer producer) { - final Initializer existing = initializerMap.get( navigablePath ); - if ( existing != null ) { - if ( fetchedModelPart.getNavigableRole().equals( - existing.getInitializedPart().getNavigableRole() ) ) { - ResultsLogger.RESULTS_MESSAGE_LOGGER.tracef( - "Returning previously-registered initializer : %s", - existing - ); - return existing; - } - } - - final Initializer initializer = producer.createInitializer( resultGraphNode, parent, this ); - ResultsLogger.RESULTS_MESSAGE_LOGGER.tracef( - "Registering initializer : %s", - initializer - ); - - if ( initializer instanceof AbstractImmediateCollectionInitializer ) { - hasCollectionInitializers = true; - } - initializerMap.put( navigablePath, initializer ); - initializerListBuilder.addInitializer( initializer ); - - return initializer; - } - - @Override - public SqlAstCreationContext getSqlAstCreationContext() { - return sessionFactory; - } - - @Override - public ExecutionContext getExecutionContext() { - return executionContext; - } - } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/RowProcessingStateStandardImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/RowProcessingStateStandardImpl.java index d996a280c7..0c02d031c7 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/RowProcessingStateStandardImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/RowProcessingStateStandardImpl.java @@ -6,6 +6,7 @@ */ package org.hibernate.sql.results.internal; +import org.hibernate.LockMode; import org.hibernate.engine.spi.CollectionKey; import org.hibernate.engine.spi.EntityHolder; import org.hibernate.metamodel.mapping.EntityMappingType; @@ -15,6 +16,7 @@ import org.hibernate.query.spi.QueryParameterBindings; import org.hibernate.sql.exec.internal.BaseExecutionContext; import org.hibernate.sql.exec.spi.Callback; import org.hibernate.sql.exec.spi.ExecutionContext; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.entity.EntityFetch; import org.hibernate.sql.results.jdbc.internal.JdbcValuesCacheHit; import org.hibernate.sql.results.jdbc.internal.JdbcValuesSourceProcessingStateStandardImpl; @@ -33,6 +35,9 @@ public class RowProcessingStateStandardImpl extends BaseExecutionContext impleme private final RowReader rowReader; private final JdbcValues jdbcValues; private final ExecutionContext executionContext; + private final boolean needsResolveState; + + private final InitializerData[] initializerData; public RowProcessingStateStandardImpl( JdbcValuesSourceProcessingStateStandardImpl resultSetProcessingState, @@ -44,6 +49,9 @@ public class RowProcessingStateStandardImpl extends BaseExecutionContext impleme this.executionContext = executionContext; this.rowReader = rowReader; this.jdbcValues = jdbcValues; + this.needsResolveState = !isQueryCacheHit() + && getQueryOptions().isResultCachingEnabled() == Boolean.TRUE; + this.initializerData = new InitializerData[rowReader.getInitializerCount()]; } @Override @@ -51,6 +59,37 @@ public class RowProcessingStateStandardImpl extends BaseExecutionContext impleme return resultSetProcessingState; } + @Override + public LockMode determineEffectiveLockMode(String alias) { + if ( jdbcValues.usesFollowOnLocking() ) { + // If follow-on locking is used, we must omit the lock options here, + // because these lock options are only for Initializers. + // If we wouldn't omit this, the follow-on lock requests would be no-ops, + // because the EntityEntrys would already have the desired lock mode + return LockMode.NONE; + } + final LockMode effectiveLockMode = resultSetProcessingState.getQueryOptions().getLockOptions() + .getEffectiveLockMode( alias ); + return effectiveLockMode == LockMode.NONE + ? jdbcValues.getValuesMapping().determineDefaultLockMode( alias, effectiveLockMode ) + : effectiveLockMode; + } + + @Override + public boolean needsResolveState() { + return needsResolveState; + } + + @Override + public T getInitializerData(int initializerId) { + return (T) initializerData[initializerId]; + } + + @Override + public void setInitializerData(int initializerId, InitializerData state) { + initializerData[initializerId] = state; + } + @Override public RowReader getRowReader() { return rowReader; @@ -122,11 +161,6 @@ public class RowProcessingStateStandardImpl extends BaseExecutionContext impleme return jdbcValues instanceof JdbcValuesCacheHit; } - @Override - public void finishRowProcessing() { - jdbcValues.finishRowProcessing( this ); - } - @Override public void finishRowProcessing(boolean wasAdded) { jdbcValues.finishRowProcessing( this, wasAdded ); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardRowReader.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardRowReader.java index 3296101958..d1f2115abb 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardRowReader.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardRowReader.java @@ -13,9 +13,9 @@ import org.hibernate.engine.spi.EntityKey; import org.hibernate.sql.results.LoadingLogger; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Initializer; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.entity.EntityInitializer; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingState; +import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingResolution; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.sql.results.spi.RowReader; import org.hibernate.sql.results.spi.RowTransformer; @@ -30,40 +30,54 @@ import org.jboss.logging.Logger; */ @SuppressWarnings("rawtypes") public class StandardRowReader implements RowReader { - private final List> resultAssemblers; - private final Initializer[] resultInitializers; - private final InitializersList initializersList; + private final DomainResultAssembler[] resultAssemblers; + private final Initializer[] resultInitializers; + private final InitializerData[] resultInitializersData; + private final Initializer[] initializers; + private final InitializerData[] initializersData; + private final Initializer[] sortedForResolveInstance; + private final InitializerData[] sortedForResolveInstanceData; private final boolean hasCollectionInitializers; private final RowTransformer rowTransformer; private final Class domainResultJavaType; - private final int assemblerCount; - private static final Logger LOGGER = LoadingLogger.LOGGER; public StandardRowReader( - List> resultAssemblers, + JdbcValuesMappingResolution jdbcValuesMappingResolution, + RowTransformer rowTransformer, + Class domainResultJavaType) { + this( + jdbcValuesMappingResolution.getDomainResultAssemblers(), + jdbcValuesMappingResolution.getResultInitializers(), + jdbcValuesMappingResolution.getInitializers(), + jdbcValuesMappingResolution.getSortedForResolveInstance(), + jdbcValuesMappingResolution.hasCollectionInitializers(), + rowTransformer, + domainResultJavaType + ); + } + + public StandardRowReader( + DomainResultAssembler[] resultAssemblers, + Initializer[] resultInitializers, + Initializer[] initializers, + Initializer[] sortedForResolveInitializers, boolean hasCollectionInitializers, - InitializersList initializersList, RowTransformer rowTransformer, Class domainResultJavaType) { this.resultAssemblers = resultAssemblers; - this.resultInitializers = getResultInitializers( resultAssemblers ); - this.initializersList = initializersList; + this.resultInitializers = (Initializer[]) resultInitializers; + this.resultInitializersData = new InitializerData[resultInitializers.length]; + this.initializers = (Initializer[]) initializers; + this.initializersData = new InitializerData[initializers.length]; + this.sortedForResolveInstance = (Initializer[]) sortedForResolveInitializers; + this.sortedForResolveInstanceData = new InitializerData[sortedForResolveInstance.length]; this.hasCollectionInitializers = hasCollectionInitializers; this.rowTransformer = rowTransformer; - this.assemblerCount = resultAssemblers.size(); this.domainResultJavaType = domainResultJavaType; } - private static Initializer[] getResultInitializers(List> resultAssemblers) { - final ArrayList initializers = new ArrayList<>( resultAssemblers.size() ); - for ( DomainResultAssembler resultAssembler : resultAssemblers ) { - resultAssembler.forEachResultAssembler( (initializer, list) -> list.add( initializer ), initializers ); - } - return initializers.toArray(Initializer.EMPTY_ARRAY); - } - @Override public Class getDomainResultResultJavaType() { return domainResultJavaType; @@ -71,8 +85,8 @@ public class StandardRowReader implements RowReader { @Override public Class getResultJavaType() { - if ( resultAssemblers.size() == 1 ) { - return resultAssemblers.get( 0 ).getAssembledJavaType().getJavaTypeClass(); + if ( resultAssemblers.length == 1 ) { + return resultAssemblers[0].getAssembledJavaType().getJavaTypeClass(); } return Object[].class; @@ -80,7 +94,7 @@ public class StandardRowReader implements RowReader { @Override public List> getResultJavaTypes() { - List> javaTypes = new ArrayList<>( resultAssemblers.size() ); + List> javaTypes = new ArrayList<>( resultAssemblers.length ); for ( DomainResultAssembler resultAssembler : resultAssemblers ) { javaTypes.add( resultAssembler.getAssembledJavaType() ); } @@ -88,26 +102,20 @@ public class StandardRowReader implements RowReader { } @Override - @Deprecated - public List getInitializers() { - return initializersList.asList(); - } - - @Override - public InitializersList getInitializersList() { - return initializersList; + public int getInitializerCount() { + return initializers.length; } @Override public @Nullable EntityKey resolveSingleResultEntityKey(RowProcessingState rowProcessingState) { - final EntityInitializer entityInitializer = resultInitializers.length == 0 + final EntityInitializer entityInitializer = resultInitializers.length == 0 ? null : resultInitializers[0].asEntityInitializer(); if ( entityInitializer == null ) { return null; } final EntityKey entityKey = entityInitializer.resolveEntityKeyOnly( rowProcessingState ); - initializersList.finishUpRow(); + finishUpRow(); return entityKey; } @@ -117,49 +125,67 @@ public class StandardRowReader implements RowReader { } @Override - public T readRow(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) { - LOGGER.trace( "StandardRowReader#readRow" ); - coordinateInitializers(); + public T readRow(RowProcessingState rowProcessingState) { + coordinateInitializers( rowProcessingState ); - final Object[] resultRow = new Object[ assemblerCount ]; - final boolean debugEnabled = LOGGER.isDebugEnabled(); + final Object[] resultRow = new Object[ resultAssemblers.length ]; - for ( int i = 0; i < assemblerCount; i++ ) { - final DomainResultAssembler assembler = resultAssemblers.get( i ); - if ( debugEnabled ) { - LOGGER.debugf( "Calling top-level assembler (%s / %s) : %s", i, assemblerCount, assembler ); - } - resultRow[i] = assembler.assemble( rowProcessingState, options ); + for ( int i = 0; i < resultAssemblers.length; i++ ) { + final DomainResultAssembler assembler = resultAssemblers[i]; + resultRow[i] = assembler.assemble( rowProcessingState ); } - afterRow(); + afterRow( rowProcessingState ); return rowTransformer.transformRow( resultRow ); } - private void afterRow() { - LOGGER.trace( "StandardRowReader#afterRow" ); - initializersList.finishUpRow(); + private void afterRow(RowProcessingState rowProcessingState) { + finishUpRow(); } - private void coordinateInitializers() { - for ( Initializer initializer : resultInitializers ) { - initializer.resolveKey(); + private void finishUpRow() { + for ( InitializerData data : initializersData ) { + data.setState( Initializer.State.UNINITIALIZED ); + } + } + + private void coordinateInitializers(RowProcessingState rowProcessingState) { + for ( int i = 0; i < resultInitializers.length; i++ ) { + resultInitializers[i].resolveKey( resultInitializersData[i] ); + } + for ( int i = 0; i < sortedForResolveInstance.length; i++ ) { + if ( sortedForResolveInstanceData[i].getState() == Initializer.State.KEY_RESOLVED ) { + sortedForResolveInstance[i].resolveInstance( sortedForResolveInstanceData[i] ); + } + } + for ( int i = 0; i < initializers.length; i++ ) { + if ( initializersData[i].getState() == Initializer.State.RESOLVED ) { + initializers[i].initializeInstance( initializersData[i] ); + } } - initializersList.resolveInstances(); - initializersList.initializeInstance(); } @Override public void startLoading(RowProcessingState processingState) { - for ( Initializer initializer : resultInitializers ) { + for ( int i = 0; i < resultInitializers.length; i++ ) { + final Initializer initializer = resultInitializers[i]; initializer.startLoading( processingState ); + resultInitializersData[i] = initializer.getData( processingState ); + } + for ( int i = 0; i < sortedForResolveInstance.length; i++ ) { + sortedForResolveInstanceData[i] = sortedForResolveInstance[i].getData( processingState ); + } + for ( int i = 0; i < initializers.length; i++ ) { + initializersData[i] = initializers[i].getData( processingState ); } } @Override - public void finishUp(JdbcValuesSourceProcessingState processingState) { - initializersList.endLoading( processingState.getExecutionContext() ); + public void finishUp(RowProcessingState rowProcessingState) { + for ( int i = 0; i < initializers.length; i++ ) { + initializers[i].endLoading( initializersData[i] ); + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularBiDirectionalFetchImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularBiDirectionalFetchImpl.java index 2bc7b545ea..aabb9471f0 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularBiDirectionalFetchImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularBiDirectionalFetchImpl.java @@ -18,10 +18,10 @@ import org.hibernate.sql.results.graph.BiDirectionalFetch; import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.FetchParent; -import org.hibernate.sql.results.graph.FetchParentAccess; +import org.hibernate.sql.results.graph.Initializer; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.entity.EntityInitializer; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.descriptor.java.JavaType; @@ -96,12 +96,7 @@ public class CircularBiDirectionalFetchImpl implements BiDirectionalFetch { } @Override - public DomainResultAssembler createAssembler(FetchParentAccess parentAccess, AssemblerCreationState creationState) { - return createAssembler( (InitializerParent) parentAccess, creationState ); - } - - @Override - public DomainResultAssembler createAssembler(InitializerParent parent, AssemblerCreationState creationState) { + public DomainResultAssembler createAssembler(InitializerParent parent, AssemblerCreationState creationState) { return new CircularBiDirectionalFetchAssembler( getResultJavaType(), keyResult == null ? null : keyResult.createResultAssembler( parent, creationState ), @@ -109,7 +104,7 @@ public class CircularBiDirectionalFetchImpl implements BiDirectionalFetch { ); } - private EntityInitializer resolveCircularInitializer(InitializerParent parent) { + private EntityInitializer resolveCircularInitializer(InitializerParent parent) { while (parent != null && getReferencedPath().isParent( parent.getNavigablePath() ) ) { parent = parent.getParent(); } @@ -120,36 +115,37 @@ public class CircularBiDirectionalFetchImpl implements BiDirectionalFetch { private static class CircularBiDirectionalFetchAssembler implements DomainResultAssembler { private final JavaType javaType; private final @Nullable DomainResultAssembler keyDomainResultAssembler; - private final EntityInitializer initializer; + private final EntityInitializer initializer; public CircularBiDirectionalFetchAssembler( JavaType javaType, @Nullable DomainResultAssembler keyDomainResultAssembler, - EntityInitializer initializer) { + EntityInitializer initializer) { //noinspection unchecked this.javaType = (JavaType) javaType; this.keyDomainResultAssembler = keyDomainResultAssembler; - this.initializer = initializer; + this.initializer = (EntityInitializer) initializer; } @Override - public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) { + public Object assemble(RowProcessingState rowProcessingState) { if ( keyDomainResultAssembler != null ) { - final Object foreignKey = keyDomainResultAssembler.assemble( rowProcessingState, options ); + final Object foreignKey = keyDomainResultAssembler.assemble( rowProcessingState ); if ( foreignKey == null ) { return null; } } - initializer.resolveInstance(); - final Object initializedInstance = initializer.getInitializedInstance(); + final InitializerData data = initializer.getData( rowProcessingState ); + initializer.resolveInstance( data ); + final Object initializedInstance = initializer.getEntityInstance( data ); final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( initializedInstance ); if ( lazyInitializer != null ) { - final Class concreteProxyClass = initializer.getConcreteDescriptor().getConcreteProxyClass(); + final Class concreteProxyClass = initializer.getConcreteDescriptor( data ).getConcreteProxyClass(); if ( concreteProxyClass.isInstance( initializedInstance ) ) { return initializedInstance; } else { - initializer.initializeInstance(); + initializer.initializeInstance( rowProcessingState ); return lazyInitializer.getImplementation(); } } @@ -163,6 +159,11 @@ public class CircularBiDirectionalFetchImpl implements BiDirectionalFetch { } } + @Override + public @Nullable Initializer getInitializer() { + return keyDomainResultAssembler == null ? null : keyDomainResultAssembler.getInitializer(); + } + @Override public JavaType getAssembledJavaType() { return javaType; diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularFetchImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularFetchImpl.java index be23380cdd..aa81deb9ae 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularFetchImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularFetchImpl.java @@ -18,15 +18,14 @@ import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.FetchParent; -import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Initializer; -import org.hibernate.sql.results.graph.basic.BasicResultAssembler; +import org.hibernate.sql.results.graph.InitializerData; +import org.hibernate.sql.results.graph.basic.BasicFetch; import org.hibernate.sql.results.graph.InitializerParent; import org.hibernate.sql.results.graph.entity.EntityInitializer; import org.hibernate.sql.results.graph.entity.internal.AbstractNonJoinedEntityFetch; import org.hibernate.sql.results.graph.entity.internal.EntityDelayedFetchInitializer; import org.hibernate.sql.results.graph.entity.internal.EntitySelectFetchInitializerBuilder; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.type.descriptor.java.JavaType; @@ -93,14 +92,7 @@ public class CircularFetchImpl extends AbstractNonJoinedEntityFetch implements B @Override public DomainResultAssembler createAssembler( - FetchParentAccess parentAccess, - AssemblerCreationState creationState) { - return createAssembler( (InitializerParent) parentAccess, creationState ); - } - - @Override - public DomainResultAssembler createAssembler( - InitializerParent parent, + InitializerParent parent, AssemblerCreationState creationState) { return new CircularFetchAssembler( getResultJavaType(), @@ -109,7 +101,7 @@ public class CircularFetchImpl extends AbstractNonJoinedEntityFetch implements B } @Override - public EntityInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { + public EntityInitializer createInitializer(InitializerParent parent, AssemblerCreationState creationState) { if ( timing == FetchTiming.IMMEDIATE ) { return buildEntitySelectFetchInitializer( parent, @@ -127,39 +119,15 @@ public class CircularFetchImpl extends AbstractNonJoinedEntityFetch implements B getNavigablePath(), getFetchedMapping(), isSelectByUniqueKey(), - getKeyResult().createResultAssembler( parent, creationState ), - getDiscriminatorFetch() != null - ? (BasicResultAssembler) getDiscriminatorFetch().createResultAssembler( parent, creationState ) - : null + getKeyResult(), + getDiscriminatorFetch(), + creationState ); } } - /** - * @deprecated Use {@link #buildEntitySelectFetchInitializer(InitializerParent, ToOneAttributeMapping, EntityPersister, DomainResult, NavigablePath, boolean, AssemblerCreationState)} instead. - */ - @Deprecated(forRemoval = true) - protected EntityInitializer buildEntitySelectFetchInitializer( - FetchParentAccess parentAccess, - ToOneAttributeMapping fetchable, - EntityPersister entityPersister, - DomainResult keyResult, - NavigablePath navigablePath, - boolean selectByUniqueKey, - AssemblerCreationState creationState) { - return buildEntitySelectFetchInitializer( - (InitializerParent) parentAccess, - fetchable, - entityPersister, - keyResult, - navigablePath, - selectByUniqueKey, - creationState - ); - } - - protected EntityInitializer buildEntitySelectFetchInitializer( - InitializerParent parent, + protected EntityInitializer buildEntitySelectFetchInitializer( + InitializerParent parent, ToOneAttributeMapping fetchable, EntityPersister entityPersister, DomainResult keyResult, @@ -177,67 +145,49 @@ public class CircularFetchImpl extends AbstractNonJoinedEntityFetch implements B ); } - /** - * @deprecated Use {@link #buildEntityDelayedFetchInitializer(InitializerParent, NavigablePath, ToOneAttributeMapping, boolean, DomainResultAssembler, BasicResultAssembler)} instead. - */ - @Deprecated(forRemoval = true) - protected EntityInitializer buildEntityDelayedFetchInitializer( - FetchParentAccess parentAccess, + protected EntityInitializer buildEntityDelayedFetchInitializer( + InitializerParent parent, NavigablePath referencedPath, ToOneAttributeMapping fetchable, boolean selectByUniqueKey, - DomainResultAssembler resultAssembler, - BasicResultAssembler discriminatorAssembler) { - return buildEntityDelayedFetchInitializer( - (InitializerParent) parentAccess, - referencedPath, - fetchable, - selectByUniqueKey, - resultAssembler, - discriminatorAssembler - ); - } - - protected EntityInitializer buildEntityDelayedFetchInitializer( - InitializerParent parent, - NavigablePath referencedPath, - ToOneAttributeMapping fetchable, - boolean selectByUniqueKey, - DomainResultAssembler resultAssembler, - BasicResultAssembler discriminatorAssembler) { + DomainResult keyResult, + BasicFetch discriminatorFetch, + AssemblerCreationState creationState) { return new EntityDelayedFetchInitializer( parent, referencedPath, fetchable, selectByUniqueKey, - resultAssembler, - discriminatorAssembler + keyResult, + discriminatorFetch, + creationState ); } private static class CircularFetchAssembler implements DomainResultAssembler { - private final EntityInitializer initializer; + private final EntityInitializer initializer; private final JavaType assembledJavaType; - public CircularFetchAssembler(JavaType assembledJavaType, EntityInitializer initializer) { + public CircularFetchAssembler(JavaType assembledJavaType, EntityInitializer initializer) { //noinspection unchecked this.assembledJavaType = (JavaType) assembledJavaType; - this.initializer = initializer; + this.initializer = (EntityInitializer) initializer; } @Override - public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) { - initializer.resolveInstance(); - return initializer.getInitializedInstance(); + public Object assemble(RowProcessingState rowProcessingState) { + final InitializerData data = initializer.getData( rowProcessingState ); + initializer.resolveInstance( data ); + return initializer.getEntityInstance( data ); } @Override - public @Nullable Initializer getInitializer() { + public @Nullable Initializer getInitializer() { return initializer; } @Override - public void forEachResultAssembler(BiConsumer consumer, X arg) { + public void forEachResultAssembler(BiConsumer, X> consumer, X arg) { if ( initializer.isResultInitializer() ) { consumer.accept( initializer, arg ); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesCacheHit.java b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesCacheHit.java index 0a1a6e4501..832a904bdf 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesCacheHit.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesCacheHit.java @@ -217,6 +217,11 @@ public class JdbcValuesCacheHit extends AbstractJdbcValues { return resolvedMapping; } + @Override + public boolean usesFollowOnLocking() { + return true; + } + @Override public Object getCurrentRowValue(int valueIndex) { if ( position >= numberOfRows ) { @@ -235,15 +240,16 @@ public class JdbcValuesCacheHit extends AbstractJdbcValues { } } - @Override - public void finishRowProcessing(RowProcessingState rowProcessingState) { - } - @Override public void finishUp(SharedSessionContractImplementor session) { cachedResults = null; } + @Override + public void finishRowProcessing(RowProcessingState rowProcessingState, boolean wasAdded) { + // No-op + } + @Override public void setFetchSize(int fetchSize) {} } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesMappingResolutionImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesMappingResolutionImpl.java new file mode 100644 index 0000000000..6fc595bbca --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesMappingResolutionImpl.java @@ -0,0 +1,74 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.sql.results.jdbc.internal; + +import java.util.ArrayList; + +import org.hibernate.sql.results.graph.DomainResultAssembler; +import org.hibernate.sql.results.graph.Initializer; +import org.hibernate.sql.results.internal.InitializersList; +import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingResolution; + +public class JdbcValuesMappingResolutionImpl implements JdbcValuesMappingResolution { + + private final DomainResultAssembler[] domainResultAssemblers; + private final Initializer[] resultInitializers; + private final boolean hasCollectionInitializers; + private final InitializersList initializersList; + + public JdbcValuesMappingResolutionImpl( + DomainResultAssembler[] domainResultAssemblers, + boolean hasCollectionInitializers, + InitializersList initializersList) { + this( domainResultAssemblers, getResultInitializers( domainResultAssemblers ), hasCollectionInitializers, initializersList ); + } + + private JdbcValuesMappingResolutionImpl( + DomainResultAssembler[] domainResultAssemblers, + Initializer[] resultInitializers, + boolean hasCollectionInitializers, + InitializersList initializersList) { + this.domainResultAssemblers = domainResultAssemblers; + this.resultInitializers = resultInitializers; + this.hasCollectionInitializers = hasCollectionInitializers; + this.initializersList = initializersList; + } + + private static Initializer[] getResultInitializers(DomainResultAssembler[] resultAssemblers) { + final ArrayList> initializers = new ArrayList<>( resultAssemblers.length ); + for ( DomainResultAssembler resultAssembler : resultAssemblers ) { + resultAssembler.forEachResultAssembler( (initializer, list) -> list.add( initializer ), initializers ); + } + return initializers.toArray(Initializer.EMPTY_ARRAY); + } + + @Override + public DomainResultAssembler[] getDomainResultAssemblers() { + return domainResultAssemblers; + } + + @Override + public boolean hasCollectionInitializers() { + return hasCollectionInitializers; + } + + @Override + public Initializer[] getResultInitializers() { + return resultInitializers; + } + + @Override + public Initializer[] getInitializers() { + return initializersList.getInitializers(); + } + + @Override + public Initializer[] getSortedForResolveInstance() { + return initializersList.getSortedForResolveInstance(); + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesResultSetImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesResultSetImpl.java index 36a27fea34..05d3728fbe 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesResultSetImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesResultSetImpl.java @@ -41,6 +41,7 @@ public class JdbcValuesResultSetImpl extends AbstractJdbcValues { private final ResultSetAccess resultSetAccess; private final JdbcValuesMapping valuesMapping; private final ExecutionContext executionContext; + private final boolean usesFollowOnLocking; private final SqlSelection[] sqlSelections; private final BitSet initializedIndexes; @@ -56,6 +57,7 @@ public class JdbcValuesResultSetImpl extends AbstractJdbcValues { QueryKey queryCacheKey, String queryIdentifier, QueryOptions queryOptions, + boolean usesFollowOnLocking, JdbcValuesMapping valuesMapping, JdbcValuesMetadata metadataForCache, ExecutionContext executionContext) { @@ -69,6 +71,7 @@ public class JdbcValuesResultSetImpl extends AbstractJdbcValues { this.resultSetAccess = resultSetAccess; this.valuesMapping = valuesMapping; this.executionContext = executionContext; + this.usesFollowOnLocking = usesFollowOnLocking; final int rowSize = valuesMapping.getRowSize(); this.sqlSelections = new SqlSelection[rowSize]; @@ -338,8 +341,8 @@ public class JdbcValuesResultSetImpl extends AbstractJdbcValues { } @Override - public void finishRowProcessing(RowProcessingState rowProcessingState) { - super.finishRowProcessing( rowProcessingState, false ); + public boolean usesFollowOnLocking() { + return usesFollowOnLocking; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesSourceProcessingStateStandardImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesSourceProcessingStateStandardImpl.java index ee85701d99..41a1cdc6de 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesSourceProcessingStateStandardImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesSourceProcessingStateStandardImpl.java @@ -41,7 +41,7 @@ public class JdbcValuesSourceProcessingStateStandardImpl implements JdbcValuesSo private List loadingEntityHolders; private List reloadedEntityHolders; private Map loadingCollectionMap; - private List arrayInitializers; + private List> arrayInitializers; private final PreLoadEvent preLoadEvent; private final PostLoadEvent postLoadEvent; diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/StandardJdbcValuesMapping.java b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/StandardJdbcValuesMapping.java index c9c6683cdf..96f8a305f1 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/StandardJdbcValuesMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/StandardJdbcValuesMapping.java @@ -7,14 +7,29 @@ package org.hibernate.sql.results.jdbc.internal; import java.util.List; +import java.util.function.Supplier; +import org.hibernate.LockMode; +import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.metamodel.mapping.ModelPart; +import org.hibernate.spi.NavigablePath; +import org.hibernate.sql.ast.spi.SqlAstCreationContext; import org.hibernate.sql.ast.spi.SqlSelection; +import org.hibernate.sql.results.ResultsLogger; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; +import org.hibernate.sql.results.graph.FetchParent; +import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.InitializerParent; +import org.hibernate.sql.results.graph.InitializerProducer; +import org.hibernate.sql.results.graph.collection.internal.AbstractImmediateCollectionInitializer; +import org.hibernate.sql.results.graph.instantiation.DynamicInstantiationResult; +import org.hibernate.sql.results.internal.InitializersList; +import org.hibernate.sql.results.internal.NavigablePathMapToInitializer; import org.hibernate.sql.results.jdbc.spi.JdbcValuesMapping; +import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingResolution; /** * @author Steve Ebersole @@ -22,6 +37,7 @@ import org.hibernate.sql.results.jdbc.spi.JdbcValuesMapping; public class StandardJdbcValuesMapping implements JdbcValuesMapping { private final List sqlSelections; private final List> domainResults; + private JdbcValuesMappingResolutionImpl resolution; public StandardJdbcValuesMapping( List sqlSelections, @@ -46,17 +62,141 @@ public class StandardJdbcValuesMapping implements JdbcValuesMapping { } @Override - public List> resolveAssemblers(AssemblerCreationState creationState) { + public JdbcValuesMappingResolution resolveAssemblers(SessionFactoryImplementor sessionFactory) { + final JdbcValuesMappingResolutionImpl resolution = this.resolution; + if ( resolution != null ) { + return resolution; + } + final AssemblerCreationStateImpl creationState = new AssemblerCreationStateImpl( + this, + sessionFactory + ); + + DomainResultAssembler[] domainResultAssemblers = resolveAssemblers( creationState ).toArray(new DomainResultAssembler[0]); + creationState.initializerMap.logInitializers(); + return this.resolution = new JdbcValuesMappingResolutionImpl( + domainResultAssemblers, + creationState.hasCollectionInitializers, + creationState.initializerListBuilder.build() + ); + } + + private List> resolveAssemblers(AssemblerCreationState creationState) { final List> assemblers = CollectionHelper.arrayList( domainResults.size() ); //noinspection ForLoopReplaceableByForEach for ( int i = 0; i < domainResults.size(); i++ ) { final DomainResultAssembler resultAssembler = domainResults.get( i ) - .createResultAssembler( (InitializerParent) null, creationState ); + .createResultAssembler( null, creationState ); assemblers.add( resultAssembler ); } return assemblers; } + + @Override + public LockMode determineDefaultLockMode(String alias, LockMode defaultLockMode) { + return defaultLockMode; + } + + private static class AssemblerCreationStateImpl implements AssemblerCreationState { + private final JdbcValuesMapping jdbcValuesMapping; + private final SessionFactoryImplementor sessionFactory; + //custom Map + private final NavigablePathMapToInitializer initializerMap = new NavigablePathMapToInitializer(); + private final InitializersList.Builder initializerListBuilder = new InitializersList.Builder(); + private int initializerId; + boolean hasCollectionInitializers; + Boolean dynamicInstantiation; + + public AssemblerCreationStateImpl( + JdbcValuesMapping jdbcValuesMapping, + SessionFactoryImplementor sessionFactory) { + this.jdbcValuesMapping = jdbcValuesMapping; + this.sessionFactory = sessionFactory; + } + + @Override + public boolean isDynamicInstantiation() { + if ( dynamicInstantiation == null ) { + dynamicInstantiation = jdbcValuesMapping.getDomainResults() + .stream() + .anyMatch( domainResult -> domainResult instanceof DynamicInstantiationResult ); + } + return dynamicInstantiation; + } + + @Override + public int acquireInitializerId() { + return initializerId++; + } + + @Override + public Initializer resolveInitializer( + NavigablePath navigablePath, + ModelPart fetchedModelPart, + Supplier> producer) { + return resolveInitializer( + navigablePath, + fetchedModelPart, + null, + null, + (resultGraphNode, parent, creationState) -> producer.get() + ); + } + + @Override + public

Initializer resolveInitializer( + P resultGraphNode, + InitializerParent parent, + InitializerProducer

producer) { + return resolveInitializer( + resultGraphNode.getNavigablePath(), + resultGraphNode.getReferencedModePart(), + resultGraphNode, + parent, + producer + ); + } + + public Initializer resolveInitializer( + NavigablePath navigablePath, + ModelPart fetchedModelPart, + T resultGraphNode, + InitializerParent parent, + InitializerProducer producer) { + final Initializer existing = initializerMap.get( navigablePath ); + if ( existing != null ) { + if ( fetchedModelPart.getNavigableRole().equals( + existing.getInitializedPart().getNavigableRole() ) ) { + ResultsLogger.RESULTS_MESSAGE_LOGGER.tracef( + "Returning previously-registered initializer : %s", + existing + ); + return existing; + } + } + + final Initializer initializer = producer.createInitializer( resultGraphNode, parent, this ); + ResultsLogger.RESULTS_MESSAGE_LOGGER.tracef( + "Registering initializer : %s", + initializer + ); + + if ( initializer instanceof AbstractImmediateCollectionInitializer ) { + hasCollectionInitializers = true; + } + initializerMap.put( navigablePath, initializer ); + initializerListBuilder.addInitializer( initializer ); + + return initializer; + } + + @Override + public SqlAstCreationContext getSqlAstCreationContext() { + return sessionFactory; + } + + } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/spi/JdbcValues.java b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/spi/JdbcValues.java index cf3098a07a..3819eacf85 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/spi/JdbcValues.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/spi/JdbcValues.java @@ -19,6 +19,8 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor; public interface JdbcValues { JdbcValuesMapping getValuesMapping(); + boolean usesFollowOnLocking(); + /** * Advances the "cursor position" and returns a boolean indicating whether * there is a row available to read via {@link #getCurrentRowValue(int)}. @@ -74,15 +76,7 @@ public interface JdbcValues { */ Object getCurrentRowValue(int valueIndex); - /** - * @deprecated Use {@link #finishRowProcessing(RowProcessingState, boolean)} instead - */ - @Deprecated(forRemoval = true) - void finishRowProcessing(RowProcessingState rowProcessingState); - - default void finishRowProcessing(RowProcessingState rowProcessingState, boolean wasAdded) { - finishRowProcessing( rowProcessingState ); - } + void finishRowProcessing(RowProcessingState rowProcessingState, boolean wasAdded); /** * Give implementations a chance to finish processing diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/spi/JdbcValuesMapping.java b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/spi/JdbcValuesMapping.java index 42a41d2a07..ce31dd93c5 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/spi/JdbcValuesMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/spi/JdbcValuesMapping.java @@ -8,6 +8,8 @@ package org.hibernate.sql.results.jdbc.spi; import java.util.List; +import org.hibernate.LockMode; +import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResultAssembler; @@ -33,5 +35,7 @@ public interface JdbcValuesMapping { List> getDomainResults(); - List> resolveAssemblers(AssemblerCreationState creationState); + JdbcValuesMappingResolution resolveAssemblers(SessionFactoryImplementor sessionFactory); + + LockMode determineDefaultLockMode(String alias, LockMode defaultLockMode); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/spi/JdbcValuesMappingResolution.java b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/spi/JdbcValuesMappingResolution.java new file mode 100644 index 0000000000..8a14507221 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/spi/JdbcValuesMappingResolution.java @@ -0,0 +1,31 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.sql.results.jdbc.spi; + +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.sql.results.graph.DomainResultAssembler; +import org.hibernate.sql.results.graph.Initializer; + +/** + * The "resolved" form of {@link JdbcValuesMapping} providing access + * to resolved ({@link DomainResultAssembler}) descriptors and resolved + * initializer ({@link Initializer}) descriptors. + * + * @see JdbcValuesMapping#resolveAssemblers(SessionFactoryImplementor) + */ +public interface JdbcValuesMappingResolution { + + DomainResultAssembler[] getDomainResultAssemblers(); + + Initializer[] getResultInitializers(); + + Initializer[] getInitializers(); + + Initializer[] getSortedForResolveInstance(); + + boolean hasCollectionInitializers(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/spi/RowProcessingState.java b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/spi/RowProcessingState.java index ef03f9ef09..70fcb72fba 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/spi/RowProcessingState.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/spi/RowProcessingState.java @@ -6,8 +6,10 @@ */ package org.hibernate.sql.results.jdbc.spi; +import org.hibernate.LockMode; import org.hibernate.sql.ast.spi.SqlSelection; import org.hibernate.sql.exec.spi.ExecutionContext; +import org.hibernate.sql.results.graph.InitializerData; import org.hibernate.sql.results.graph.entity.EntityFetch; import org.hibernate.sql.results.spi.RowReader; @@ -22,6 +24,13 @@ public interface RowProcessingState extends ExecutionContext { */ JdbcValuesSourceProcessingState getJdbcValuesSourceProcessingState(); + LockMode determineEffectiveLockMode(String alias); + + boolean needsResolveState(); + + T getInitializerData(int initializerId); + void setInitializerData(int initializerId, InitializerData state); + /** * Retrieve the value corresponding to the given SqlSelection as part * of the "current JDBC row". @@ -55,18 +64,8 @@ public interface RowProcessingState extends ExecutionContext { /** * Callback at the end of processing the current "row" - * - * @deprecated Use {@link #finishRowProcessing(boolean)} instead */ - @Deprecated(forRemoval = true) - void finishRowProcessing(); - - /** - * Callback at the end of processing the current "row" - */ - default void finishRowProcessing(boolean wasAdded) { - finishRowProcessing(); - } + void finishRowProcessing(boolean wasAdded); /** * If this is a row processing state for aggregate components, diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/spi/ListResultsConsumer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/spi/ListResultsConsumer.java index 5419c5c9d7..17b12c108a 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/spi/ListResultsConsumer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/spi/ListResultsConsumer.java @@ -148,7 +148,7 @@ public class ListResultsConsumer implements ResultsConsumer, R> { JdbcValuesSourceProcessingStateStandardImpl jdbcValuesSourceProcessingState, RowProcessingStateStandardImpl rowProcessingState, RowReader rowReader) { - final PersistenceContext persistenceContext = session.getPersistenceContext(); + final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); final TypeConfiguration typeConfiguration = session.getTypeConfiguration(); final QueryOptions queryOptions = rowProcessingState.getQueryOptions(); RuntimeException ex = null; @@ -178,14 +178,14 @@ public class ListResultsConsumer implements ResultsConsumer, R> { || uniqueSemantic == UniqueSemantic.ASSERT && rowReader.hasCollectionInitializers() || uniqueSemantic == UniqueSemantic.ALLOW && isEntityResultType ) { while ( rowProcessingState.next() ) { - final boolean added = results.addUnique( rowReader.readRow( rowProcessingState, processingOptions ) ); + final boolean added = results.addUnique( rowReader.readRow( rowProcessingState ) ); rowProcessingState.finishRowProcessing( added ); readRows++; } } else if ( uniqueSemantic == UniqueSemantic.ASSERT ) { while ( rowProcessingState.next() ) { - if ( !results.addUnique( rowReader.readRow( rowProcessingState, processingOptions ) ) ) { + if ( !results.addUnique( rowReader.readRow( rowProcessingState ) ) ) { throw new HibernateException( String.format( Locale.ROOT, @@ -200,13 +200,13 @@ public class ListResultsConsumer implements ResultsConsumer, R> { } else { while ( rowProcessingState.next() ) { - results.add( rowReader.readRow( rowProcessingState, processingOptions ) ); + results.add( rowReader.readRow( rowProcessingState ) ); rowProcessingState.finishRowProcessing( true ); readRows++; } } - rowReader.finishUp( jdbcValuesSourceProcessingState ); + rowReader.finishUp( rowProcessingState ); jdbcValuesSourceProcessingState.finishUp( readRows > 1 ); //noinspection unchecked diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/spi/RowReader.java b/hibernate-core/src/main/java/org/hibernate/sql/results/spi/RowReader.java index d08084f3e5..2b44ca1ee3 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/spi/RowReader.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/spi/RowReader.java @@ -9,11 +9,7 @@ package org.hibernate.sql.results.spi; import java.util.List; import org.hibernate.engine.spi.EntityKey; -import org.hibernate.sql.results.graph.Initializer; -import org.hibernate.sql.results.internal.InitializersList; import org.hibernate.sql.results.jdbc.spi.RowProcessingState; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; -import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingState; import org.hibernate.type.descriptor.java.JavaType; import org.checkerframework.checker.nullness.qual.Nullable; @@ -48,14 +44,7 @@ public interface RowReader { */ List> getResultJavaTypes(); - /** - * The initializers associated with this reader. - * - * @see org.hibernate.sql.results.graph.DomainResult - * @deprecated Not needed anymore - */ - @Deprecated(forRemoval = true) - List getInitializers(); + int getInitializerCount(); /** * Called before reading the first row. @@ -65,21 +54,12 @@ public interface RowReader { /** * The actual coordination of reading a row */ - R readRow(RowProcessingState processingState, JdbcValuesSourceProcessingOptions options); + R readRow(RowProcessingState processingState); /** * Called at the end of processing all rows */ - void finishUp(JdbcValuesSourceProcessingState context); - - /** - * The initializers associated with this reader. - * - * @see org.hibernate.sql.results.graph.DomainResult - * @deprecated Not needed anymore. Also, was exposing internal type - */ - @Deprecated(forRemoval = true) - InitializersList getInitializersList(); + void finishUp(RowProcessingState processingState); @Nullable EntityKey resolveSingleResultEntityKey(RowProcessingState rowProcessingState); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/spi/SingleResultConsumer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/spi/SingleResultConsumer.java index f8d9d8531a..28ac3f517e 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/spi/SingleResultConsumer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/spi/SingleResultConsumer.java @@ -33,9 +33,9 @@ public class SingleResultConsumer implements ResultsConsumer { RowReader rowReader) { rowReader.startLoading( rowProcessingState ); rowProcessingState.next(); - final T result = rowReader.readRow( rowProcessingState, processingOptions ); + final T result = rowReader.readRow( rowProcessingState ); rowProcessingState.finishRowProcessing( true ); - rowReader.finishUp( jdbcValuesSourceProcessingState ); + rowReader.finishUp( rowProcessingState ); jdbcValuesSourceProcessingState.finishUp( false ); return result; } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java index ebaca4dafe..adcdc3b5cc 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java @@ -164,6 +164,10 @@ public class EntityMetamodel implements Serializable { // Improves performance of EntityKey#equals by avoiding content check in String#equals name = persistentClass.getEntityName().intern(); rootName = persistentClass.getRootClass().getEntityName().intern(); + // Make sure the hashCodes are cached + name.hashCode(); + rootName.hashCode(); + subclassId = persistentClass.getSubclassId(); identifierAttribute = PropertyFactory.buildIdentifierAttribute( diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/sql/ast/SmokeTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/ast/SmokeTests.java index 357006d430..ae0e980d07 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/sql/ast/SmokeTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/sql/ast/SmokeTests.java @@ -175,7 +175,7 @@ public class SmokeTests { // ScalarDomainResultImpl creates and caches the assembler at its creation. // this just gets access to that cached one final DomainResultAssembler resultAssembler = domainResult.createResultAssembler( - (InitializerParent) null, + null, null ); diff --git a/hibernate-envers/hibernate-envers.gradle b/hibernate-envers/hibernate-envers.gradle index c0e54a1651..95feba610f 100644 --- a/hibernate-envers/hibernate-envers.gradle +++ b/hibernate-envers/hibernate-envers.gradle @@ -51,6 +51,13 @@ configurations { } } +tasks.withType( Test.class ).each { test -> + if ( project.db == "h2" || project.db == "hsqldb" || project.db == "derby" ) { + // Parallel test runs when running with in-memory databases + test.maxParallelForks = Runtime.runtime.availableProcessors().intdiv( 2 ) ?: 1 + } +} + sourcesJar { duplicatesStrategy = DuplicatesStrategy.EXCLUDE }