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
This commit is contained in:
Christian Beikov 2024-05-28 14:38:32 +02:00
parent f86bdf08c1
commit da22678c74
138 changed files with 2802 additions and 3897 deletions

View File

@ -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

View File

@ -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() );
}

View File

@ -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

View File

@ -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);
}

View File

@ -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<EntityKey, EntityHolderImpl> 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<EntityKey, EntityHolderImpl> 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<EntityKey, EntityHolderImpl> 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<EntityKey, EntityHolderImpl> 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<EntityKey, EntityHolderImpl> 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;
}

View File

@ -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.
*

View File

@ -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;
}

View File

@ -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);

View File

@ -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(

View File

@ -298,6 +298,9 @@ public abstract class AbstractSaveEventListener<C>
persister,
false
);
if ( original.getLoadedState() != null ) {
persistenceContext.getEntityHolder( key ).setEntityEntry( original );
}
cascadeBeforeSave( source, persister, entity, context );

View File

@ -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 );

View File

@ -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 );

View File

@ -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<Object[]> rowReader = ResultsHelper.createRowReader(
executionContext,
LockOptions.NONE,
session.getFactory(),
RowTransformerArrayImpl.instance(),
Object[].class,
jdbcValues

View File

@ -97,7 +97,7 @@ public abstract class AbstractScrollableResults<R> implements ScrollableResultsI
return;
}
rowReader.finishUp( jdbcValuesSourceProcessingState );
rowReader.finishUp( rowProcessingState );
jdbcValues.finishUp( persistenceContext );
getPersistenceContext().getJdbcCoordinator().afterStatementExecution();

View File

@ -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<R> 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<R> extends AbstractScrollableResults<
last = false;
}
else {
rowReader.readRow( rowProcessingState, getProcessingOptions() );
rowReader.readRow( rowProcessingState );
rowProcessingState.finishRowProcessing( false );
}
}

View File

@ -130,7 +130,7 @@ public class ScrollableResultsImpl<R> extends AbstractScrollableResults<R> {
persistenceContext.beforeLoad();
try {
try {
currentRow = getRowReader().readRow( getRowProcessingState(), getProcessingOptions() );
currentRow = getRowReader().readRow( getRowProcessingState() );
getRowProcessingState().finishRowProcessing( true );
getJdbcValuesSourceProcessingState().finishUp( false );

View File

@ -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();

View File

@ -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<Object[]> createResultAssembler(
FetchParentAccess parentAccess,
AssemblerCreationState creationState) {
return createResultAssembler( (InitializerParent) parentAccess, creationState );
}
@Override
public DomainResultAssembler<Object[]> 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<Object[]> 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 <X> void forEachResultAssembler(BiConsumer<Initializer, X> consumer, X arg) {
public <X> void forEachResultAssembler(BiConsumer<Initializer<?>, 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<Object[]> getAssembledJavaType() {
return jtd;
}
}
}

View File

@ -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,

View File

@ -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<String, LockMode> registeredLockModes;
private final @Nullable Map<String, LockMode> registeredLockModes;
public JdbcValuesMappingImpl(
List<SqlSelection> sqlSelections,
List<DomainResult<?>> domainResults,
int rowSize,
Map<String, LockMode> registeredLockModes) {
@Nullable Map<String, LockMode> registeredLockModes) {
super( sqlSelections, domainResults );
this.rowSize = rowSize;
this.registeredLockModes = registeredLockModes;
@ -51,53 +42,7 @@ public class JdbcValuesMappingImpl extends StandardJdbcValuesMapping {
}
@Override
public List<DomainResultAssembler<?>> 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<Initializer> producer) {
return creationState.resolveInitializer( navigablePath, fetchedModelPart, producer );
}
@Override
public <P extends FetchParent> Initializer resolveInitializer(
P resultGraphNode,
InitializerParent parent,
InitializerProducer<P> 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 );
}
}

View File

@ -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;

View File

@ -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<Entit
private final boolean containsCollectionFetches;
private final String resultAlias;
private final LockMode lockMode;
public EntityResultImpl(
NavigablePath navigablePath,
@ -56,10 +54,11 @@ public class EntityResultImpl implements EntityResult, InitializerProducer<Entit
this.navigablePath = navigablePath;
this.entityValuedModelPart = entityValuedModelPart;
this.resultAlias = resultAlias;
this.lockMode = lockMode;
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
if ( resultAlias != null ) {
sqlAstCreationState.registerLockMode( resultAlias, lockMode );
}
sqlAstCreationState.getFromClauseAccess().resolveTableGroup(
navigablePath,
np -> {
@ -139,13 +138,6 @@ public class EntityResultImpl implements EntityResult, InitializerProducer<Entit
}
}
@Override
public DomainResultAssembler<?> 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<Entit
}
@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,
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<Entit
true,
creationState
);
// return new EntityResultInitializer(
// this,
// getNavigablePath(),
// lockMode,
// identifierFetch,
// discriminatorFetch,
// null,
// creationState
// );
// return new EntityInitializerImpl(
// this,
// lockMode,
// identifierFetch,
// discriminatorFetch,
// null,
// null,
// NotFoundAction.EXCEPTION,
// null,
// true,
// creationState
// );
}
}

View File

@ -114,19 +114,6 @@ public class SelfRenderingFunctionSqlAstExpression
return type;
}
@Override
public SqlSelection createSqlSelection(
int jdbcPosition,
int valuesArrayPosition,
JavaType javaType,
TypeConfiguration typeConfiguration) {
return new SqlSelectionImpl(
jdbcPosition,
valuesArrayPosition,
this,
false
);
}
@Override
public SqlSelection createSqlSelection(
int jdbcPosition,

View File

@ -16,18 +16,14 @@ import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.model.domain.DiscriminatorSqmPath;
import org.hibernate.metamodel.model.domain.internal.EmbeddedDiscriminatorSqmPath;
import org.hibernate.metamodel.model.domain.internal.EntityDiscriminatorSqmPath;
import org.hibernate.query.results.ResultSetMappingSqlSelection;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.spi.TypeConfiguration;
import static org.hibernate.query.sqm.internal.SqmMappingModelHelper.resolveMappingModelExpressible;
@ -105,15 +101,6 @@ public class DiscriminatorPathInterpretation<T> extends AbstractSqmPathInterpret
return getDiscriminatorMapping();
}
@Override
public SqlSelection createSqlSelection(
int jdbcPosition,
int valuesArrayPosition,
JavaType javaType,
TypeConfiguration typeConfiguration) {
return new ResultSetMappingSqlSelection( valuesArrayPosition, getDiscriminatorMapping() );
}
@Override
public DomainResult<T> createDomainResult(String resultVariable, DomainResultCreationState creationState) {
return getDiscriminatorMapping().createDomainResult( getNavigablePath(), getTableGroup(), resultVariable, creationState );

View File

@ -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<K, V, R extends Map.Entry<K, V>> implements Domai
@Override
public DomainResultAssembler<R> createResultAssembler(
FetchParentAccess parentAccess,
AssemblerCreationState creationState) {
return createResultAssembler( (InitializerParent) parentAccess, creationState );
}
@Override
public DomainResultAssembler<R> createResultAssembler(
InitializerParent parent,
InitializerParent<?> parent,
AssemblerCreationState creationState) {
final DomainResultAssembler<K> keyAssembler = keyResult.createResultAssembler(
(InitializerParent) null,
null,
creationState
);
final DomainResultAssembler<V> 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<R> getAssembledJavaType() {
return javaType;
}
@Override
public <X> void forEachResultAssembler(BiConsumer<Initializer, X> 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<K, V, R extends Map.Entry<K, V>> implements Domai
keyResult.collectValueIndexesToCache( valueIndexes );
valueResult.collectValueIndexesToCache( valueIndexes );
}
private static class EntryDomainResultAssembler<K, V, R> implements DomainResultAssembler<R> {
private final JavaType<R> javaType;
private final DomainResultAssembler<K> keyAssembler;
private final DomainResultAssembler<V> valueAssembler;
public EntryDomainResultAssembler(
JavaType<R> javaType, DomainResultAssembler<K> keyAssembler,
DomainResultAssembler<V> 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<R> getAssembledJavaType() {
return javaType;
}
@Override
public <X> void forEachResultAssembler(BiConsumer<Initializer<?>, X> consumer, X arg) {
keyAssembler.forEachResultAssembler( consumer, arg );
valueAssembler.forEachResultAssembler( consumer, arg );
}
}
}

View File

@ -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<Object> rowReader = (RowReader<Object>) ResultsHelper.createRowReader(
executionContext,
null,
getSessionFactory(),
RowTransformerStandardImpl.INSTANCE,
null,
jdbcValues
@ -241,18 +240,18 @@ public class OutputsImpl implements Outputs {
processingOptions
);
final ArrayList<Object> results = new ArrayList<>();
try {
final RowProcessingStateStandardImpl rowProcessingState = new RowProcessingStateStandardImpl(
jdbcValuesSourceProcessingState,
executionContext,
rowReader,
jdbcValues
);
try {
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 );
}
}

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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;

View File

@ -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<R> 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

View File

@ -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<Initializer> producer);
Supplier<Initializer<?>> producer);
<P extends FetchParent> Initializer resolveInitializer(
<P extends FetchParent> Initializer<?> resolveInitializer(
P resultGraphNode,
InitializerParent parent,
InitializerParent<?> parent,
InitializerProducer<P> producer);
SqlAstCreationContext getSqlAstCreationContext();
ExecutionContext getExecutionContext();
}

View File

@ -30,19 +30,8 @@ public interface DomainResult<J> extends DomainResultGraphNode {
/**
* Create an assembler (and any initializers) for this result.
* @deprecated Use {@link #createResultAssembler(InitializerParent, AssemblerCreationState)} instead.
*/
@Deprecated(forRemoval = true)
DomainResultAssembler<J> createResultAssembler(
FetchParentAccess parentAccess,
InitializerParent<?> parent,
AssemblerCreationState creationState);
/**
* Create an assembler (and any initializers) for this result.
*/
default DomainResultAssembler<J> createResultAssembler(
InitializerParent parent,
AssemblerCreationState creationState) {
return createResultAssembler( (FetchParentAccess) parent, creationState );
}
}

View File

@ -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<J> {
/**
* 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<J> {
assemble( rowProcessingState );
}
default @Nullable Initializer getInitializer() {
default @Nullable Initializer<?> getInitializer() {
return null;
}
@ -59,7 +51,8 @@ public interface DomainResultAssembler<J> {
* Invokes the consumer with every initializer part of this assembler that returns {@code true} for
* {@link Initializer#isResultInitializer()}.
*/
default <X> void forEachResultAssembler(BiConsumer<Initializer, X> consumer, X arg) {
default <X> void forEachResultAssembler(BiConsumer<Initializer<?>, X> consumer, X arg) {
}
}

View File

@ -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);
}

View File

@ -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 ) {

View File

@ -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<Object> 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;
}
}

View File

@ -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<Data extends InitializerData> {
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;
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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;
}
}

View File

@ -12,6 +12,6 @@ package org.hibernate.sql.results.graph;
*
* @author Steve Ebersole
*/
public interface InitializerParent extends Initializer {
public interface InitializerParent<Data extends InitializerData> extends Initializer<Data> {
}

View File

@ -13,8 +13,8 @@ package org.hibernate.sql.results.graph;
* @since 6.5
*/
public interface InitializerProducer<P extends FetchParent> {
Initializer createInitializer(
Initializer<?> createInitializer(
P resultGraphNode,
InitializerParent parent,
InitializerParent<?> parent,
AssemblerCreationState creationState);
}

View File

@ -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<J> implements DomainResultAssemb
}
@Override
public J assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) {
public J assemble(RowProcessingState rowProcessingState) {
return null;
}
@ -27,4 +26,5 @@ public class UnfetchedBasicPartResultAssembler<J> implements DomainResultAssemb
public JavaType<J> getAssembledJavaType() {
return javaType;
}
}

View File

@ -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<J> implements DomainResultAssembler<J> {
}
@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<J> implements DomainResultAssembler<J> {
public JavaType<J> getAssembledJavaType() {
return javaType;
}
}

View File

@ -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<T> implements Fetch, BasicResultGraphNode<T> {
return navigablePath;
}
@Override
public DomainResultAssembler createAssembler(
FetchParentAccess parentAccess,
AssemblerCreationState creationState) {
return createAssembler( (InitializerParent) parentAccess, creationState );
}
@Override
public DomainResultAssembler<T> createAssembler(
InitializerParent parent,
InitializerParent<?> parent,
AssemblerCreationState creationState) {
return assembler;
}
@Override
public DomainResultAssembler<T> createResultAssembler(
FetchParentAccess parentAccess,
AssemblerCreationState creationState) {
return createResultAssembler( (InitializerParent) parentAccess, creationState );
}
@Override
public DomainResultAssembler<T> createResultAssembler(
InitializerParent parent,
InitializerParent<?> parent,
AssemblerCreationState creationState) {
return assembler;
}

View File

@ -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<T> implements DomainResult<T>, BasicResultGraphNode<T>
@Override
public DomainResultAssembler<T> createResultAssembler(
FetchParentAccess parentAccess,
AssemblerCreationState creationState) {
return createResultAssembler( (InitializerParent) parentAccess, creationState );
}
@Override
public DomainResultAssembler<T> createResultAssembler(
InitializerParent parent,
InitializerParent<?> parent,
AssemblerCreationState creationState) {
return assembler;
}

View File

@ -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<J> implements DomainResultAssembler<J> {
@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

View File

@ -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<Data extends InitializerData> extends InitializerParent<Data> {
@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;
}
}

View File

@ -27,7 +27,7 @@ public interface LoadingCollectionEntry {
/**
* The initializer responsible for the loading
*/
CollectionInitializer getInitializer();
CollectionInitializer<?> getInitializer();
/**
* The collection key.

View File

@ -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<Data extends AbstractCollectionInitializer.CollectionInitializerData>
extends AbstractInitializer<Data> implements CollectionInitializer<Data> {
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;
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<InitializerData> initializer = (Initializer<InitializerData>) 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 <X> void forEachSubInitializer(BiConsumer<Initializer, X> consumer, X arg) {
protected void forEachSubInitializer(BiConsumer<Initializer<?>, 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;
}
}

View File

@ -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<Data extends AbstractImmediateCollectionInitializer.ImmediateCollectionInitializerData>
extends AbstractCollectionInitializer<Data> {
/**
* 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;
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 <X> void forEachSubInitializer(BiConsumer<Initializer, X> consumer, X arg) {
super.forEachSubInitializer( consumer, arg );
protected void forEachSubInitializer(BiConsumer<Initializer<?>, 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<InitializerData> initializer = (Initializer<InitializerData>) 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 )
);
if ( data.getCollectionInstance().wasInitialized() ) {
data.setState( State.INITIALIZED );
}
state = 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 )
);
if ( data.getCollectionInstance().wasInitialized() ) {
data.setState( State.INITIALIZED );
}
state = 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<Object> 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;
}
}

View File

@ -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<AbstractImmediateCollectionInitializer.ImmediateCollectionInitializerData> {
private static final String CONCRETE_NAME = ArrayInitializer.class.getSimpleName();
private final DomainResultAssembler<Integer> 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<Integer>) listIndexFetch.createAssembler( (InitializerParent) this, creationState );
this.elementAssembler = elementFetch.createAssembler( (InitializerParent) this, creationState );
this.listIndexAssembler = (DomainResultAssembler<Integer>) 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 <X> void forEachSubInitializer(BiConsumer<Initializer, X> consumer, X arg) {
super.forEachSubInitializer( consumer, arg );
final Initializer initializer = elementAssembler.getInitializer();
protected void forEachSubInitializer(BiConsumer<Initializer<?>, 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 );
}
}
}

View File

@ -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,

View File

@ -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<AbstractImmediateCollectionInitializer.ImmediateCollectionInitializerData> {
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 <X> void forEachSubInitializer(BiConsumer<Initializer, X> consumer, X arg) {
super.forEachSubInitializer( consumer, arg );
final Initializer initializer = elementAssembler.getInitializer();
protected void forEachSubInitializer(BiConsumer<Initializer<?>, 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 );
}
}
}

View File

@ -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,

View File

@ -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

View File

@ -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,

View File

@ -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 );
}

View File

@ -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(),

View File

@ -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<AbstractCollectionInitializer.CollectionInitializerData> {
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

View File

@ -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(),

View File

@ -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<AbstractImmediateCollectionInitializer.ImmediateCollectionInitializerData> {
private static final String CONCRETE_NAME = ListInitializer.class.getSimpleName();
private final DomainResultAssembler<Integer> 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<Integer>) listIndexFetch.createAssembler( (InitializerParent) this, creationState );
this.elementAssembler = elementFetch.createAssembler( (InitializerParent) this, creationState );
this.listIndexAssembler = (DomainResultAssembler<Integer>) 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 <X> void forEachSubInitializer(BiConsumer<Initializer, X> consumer, X arg) {
super.forEachSubInitializer( consumer, arg );
final Initializer initializer = elementAssembler.getInitializer();
protected void forEachSubInitializer(BiConsumer<Initializer<?>, 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 );
}
}
}

View File

@ -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,

View File

@ -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<AbstractImmediateCollectionInitializer.ImmediateCollectionInitializerData> {
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 <X> void forEachSubInitializer(BiConsumer<Initializer, X> consumer, X arg) {
super.forEachSubInitializer( consumer, arg );
final Initializer keyInitializer = mapKeyAssembler.getInitializer();
protected void forEachSubInitializer(BiConsumer<Initializer<?>, 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 );
}
}
}

View File

@ -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,

View File

@ -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(),

View File

@ -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<AbstractCollectionInitializer.CollectionInitializerData> {
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

View File

@ -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<AbstractImmediateCollectionInitializer.ImmediateCollectionInitializerData> {
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 <X> void forEachSubInitializer(BiConsumer<Initializer, X> consumer, X arg) {
super.forEachSubInitializer( consumer, arg );
final Initializer initializer = elementAssembler.getInitializer();
protected void forEachSubInitializer(BiConsumer<Initializer<?>, 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 );
}
}
}

View File

@ -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,

View File

@ -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();
}
}

View File

@ -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<Data extends InitializerData> extends InitializerParent<Data> {
@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;
}
}

View File

@ -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,

View File

@ -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() };
}
}

View File

@ -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() };
}
}

View File

@ -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<T> extends AbstractFetchParent implem
@Override
public DomainResultAssembler<T> createResultAssembler(
FetchParentAccess parentAccess,
AssemblerCreationState creationState) {
return createResultAssembler( (InitializerParent) parentAccess, creationState );
}
@Override
public DomainResultAssembler<T> 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<T> 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,

View File

@ -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<InitializerData> initializer;
public EmbeddableAssembler(EmbeddableInitializer initializer) {
this.initializer = initializer;
public EmbeddableAssembler(EmbeddableInitializer<?> initializer) {
this.initializer = (EmbeddableInitializer<InitializerData>) 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;
}

View File

@ -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<T> extends AbstractFetchParent imple
@Override
public DomainResultAssembler<T> createResultAssembler(
FetchParentAccess parentAccess,
AssemblerCreationState creationState) {
return createResultAssembler( (InitializerParent) parentAccess, creationState );
}
@Override
public DomainResultAssembler<T> 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<T> 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 );
}
}

View File

@ -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 );
}

View File

@ -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<T>
@Override
public DomainResultAssembler<T> createResultAssembler(
FetchParentAccess parentAccess,
AssemblerCreationState creationState) {
return createResultAssembler( (InitializerParent) parentAccess, creationState );
}
@Override
public DomainResultAssembler<T> 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<T> 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 );

View File

@ -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<EmbeddableInitializerImpl.EmbeddableInitializerData>
implements EmbeddableInitializer<EmbeddableInitializerImpl.EmbeddableInitializerData> {
private final NavigablePath navigablePath;
private final EmbeddableValuedModelPart embedded;
private final InitializerParent parent;
private final InitializerParent<InitializerData> 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<InitializerData>[][] subInitializers;
// per-row state
private final Object[] rowState;
protected Object compositeInstance;
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> T getValue(int i, Class<T> 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<InitializerData>) 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<InitializerData>[][] 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<Initializer> initializers = new ArrayList<>( subAssemblers.length );
final ArrayList<Initializer<?>> 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<InitializerData>[][]) 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<InitializerData> 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 <X> void forEachSubInitializer(BiConsumer<Initializer, X> consumer, X arg) {
if ( concreteEmbeddableType == null ) {
for ( Initializer[] initializers : subInitializers ) {
for ( Initializer initializer : initializers ) {
consumer.accept( initializer, arg );
protected void forEachSubInitializer(BiConsumer<Initializer<?>, 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> T getValue(int i, Class<T> 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" );

View File

@ -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<T> extends AbstractFetchParent implements Embe
@Override
public DomainResultAssembler<T> createResultAssembler(
FetchParentAccess parentAccess,
AssemblerCreationState creationState) {
return createResultAssembler( (InitializerParent) parentAccess, creationState );
}
@Override
public DomainResultAssembler<T> 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<T> 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 );
}
}

View File

@ -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 extends InitializerData> 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 );

View File

@ -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 );
}
}

View File

@ -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<NonAggregatedIdentifierMappingInitializer.NonAggregatedIdentifierMappingInitializerData>
implements EmbeddableInitializer<NonAggregatedIdentifierMappingInitializer.NonAggregatedIdentifierMappingInitializerData> {
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<InitializerData>[] 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> T getValue(int i, Class<T> 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<Initializer> initializers = new ArrayList<>( assemblers.length );
final ArrayList<Initializer<?>> 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<InitializerData>[]) (
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<InitializerData> 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 <X> void forEachSubInitializer(BiConsumer<Initializer, X> consumer, X arg) {
for ( Initializer initializer : initializers ) {
consumer.accept( initializer, arg );
protected void forEachSubInitializer(BiConsumer<Initializer<?>, 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> T getValue(int i, Class<T> 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;

View File

@ -23,9 +23,9 @@ public class NonAggregatedIdentifierMappingResult<T> extends EmbeddableResultImp
}
@Override
public Initializer createInitializer(
public Initializer<?> createInitializer(
EmbeddableResultImpl<T> resultGraphNode,
InitializerParent parent,
InitializerParent<?> parent,
AssemblerCreationState creationState) {
return new NonAggregatedIdentifierMappingInitializer( resultGraphNode, parent, creationState, true );
}

View File

@ -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<Data extends InitializerData> extends InitializerParent<Data> {
/**
* 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();
}

View File

@ -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 )
);
}
}

View File

@ -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<Data extends AbstractBatchEntitySelectFetchInitializer.AbstractBatchEntitySelectFetchInitializerData>
extends EntitySelectFetchInitializer<Data> implements EntityInitializer<Data> {
protected final InitializerParent parent;
private final NavigablePath navigablePath;
private final boolean isPartOfKey;
protected final EntityInitializer<InitializerData> owningEntityInitializer;
protected final EntityPersister concreteDescriptor;
protected final DomainResultAssembler<?> identifierAssembler;
protected final ToOneAttributeMapping referencedModelPart;
protected final EntityInitializer owningEntityInitializer;
protected boolean batchDisabled;
public static abstract class AbstractBatchEntitySelectFetchInitializerData extends EntitySelectFetchInitializerData {
// per-row state
protected @Nullable Object initializedEntityInstance;
protected @Nullable Object entityIdentifier;
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<InitializerData>) 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<InitializerData> initializer = (Initializer<InitializerData>) 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 ) {
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( rowProcessingState );
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 <X> void forEachSubInitializer(BiConsumer<Initializer, X> 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" );
}
}

View File

@ -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 );
}
}

View File

@ -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<EntityKey, List<ParentInfo>> toBatchLoad;
public class BatchEntityInsideEmbeddableSelectFetchInitializer extends AbstractBatchEntitySelectFetchInitializer<BatchEntityInsideEmbeddableSelectFetchInitializer.BatchEntityInsideEmbeddableSelectFetchInitializerData> {
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<EntityKey, List<ParentInfo>> 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(),
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<ParentInfo> 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();

View File

@ -20,68 +20,62 @@ 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<BatchEntitySelectFetchInitializer.BatchEntitySelectFetchInitializerData> {
protected final AttributeMapping[] parentAttributes;
protected final Setter referencedModelPartSetter;
protected final Type referencedModelPartType;
public static class BatchEntitySelectFetchInitializerData extends AbstractBatchEntitySelectFetchInitializerData {
private Map<EntityKey, List<ParentInfo>> 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<ParentInfo> getParentInfos() {
if ( toBatchLoad == null ) {
toBatchLoad = new HashMap<>();
}
return toBatchLoad.computeIfAbsent( entityKey, key -> new ArrayList<>() );
}
@Override
public boolean isEntityInitialized() {
return false;
}
private static class ParentInfo {
@ -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();
}
}

View File

@ -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<BatchInitializeEntitySelectFetchInitializer.BatchInitializeEntitySelectFetchInitializerData> {
public static class BatchInitializeEntitySelectFetchInitializerData extends AbstractBatchEntitySelectFetchInitializerData {
private final Set<EntityKey> 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;
public void endLoading(BatchInitializeEntitySelectFetchInitializerData data) {
super.endLoading( data );
final SharedSessionContractImplementor session = data.getRowProcessingState().getSession();
for ( EntityKey key : data.toBatchLoad ) {
loadInstance( key, toOneMapping, session );
}
@Override
public void endLoading(ExecutionContext executionContext) {
super.endLoading( executionContext );
final SharedSessionContractImplementor session = executionContext.getSession();
for ( EntityKey key : toBatchLoad ) {
loadInstance( key, referencedModelPart, session );
}
toBatchLoad.clear();
data.toBatchLoad.clear();
}
@Override

View File

@ -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(),

View File

@ -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<DiscriminatedEntityInitializer.DiscriminatedEntityInitializerData>
implements EntityInitializer<DiscriminatedEntityInitializer.DiscriminatedEntityInitializerData> {
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
public static class DiscriminatedEntityInitializerData extends InitializerData {
protected EntityPersister concreteDescriptor;
protected Object entityIdentifier;
protected Object entityInstance;
/**
* @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 <X> void forEachSubInitializer(BiConsumer<Initializer, X> consumer, X arg) {
final Initializer initializer = keyValueAssembler.getInitializer();
protected void forEachSubInitializer(BiConsumer<Initializer<?>, 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" );
}
}

View File

@ -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<T> extends AbstractDiscriminatedEntityRes
@Override
public DomainResultAssembler<T> createResultAssembler(
FetchParentAccess parentAccess,
AssemblerCreationState creationState) {
return createResultAssembler( (InitializerParent) parentAccess, creationState );
}
@Override
public DomainResultAssembler<T> createResultAssembler(
InitializerParent parent,
InitializerParent<?> parent,
AssemblerCreationState creationState) {
//noinspection unchecked
return new EntityAssembler(
@ -59,15 +51,15 @@ public class DiscriminatedEntityResult<T> extends AbstractDiscriminatedEntityRes
}
@Override
public Initializer createInitializer(
public Initializer<?> createInitializer(
DiscriminatedEntityResult<T> 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(),

View File

@ -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<InitializerData> initializer;
public EntityAssembler(
JavaType javaType,
EntityInitializer initializer) {
public EntityAssembler(JavaType javaType, EntityInitializer<?> initializer) {
this.javaType = javaType;
this.initializer = initializer;
this.initializer = (EntityInitializer<InitializerData>) 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;
}

View File

@ -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
);
}
}

View File

@ -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<EntityDelayedFetchInitializer.EntityDelayedFetchInitializerData>
implements EntityInitializer<EntityDelayedFetchInitializer.EntityDelayedFetchInitializerData> {
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;
public static class EntityDelayedFetchInitializerData extends InitializerData {
// per-row state
private Object entityInstance;
private Object identifier;
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 <X> void forEachSubInitializer(BiConsumer<Initializer, X> consumer, X arg) {
final Initializer initializer = identifierAssembler.getInitializer();
protected void forEachSubInitializer(BiConsumer<Initializer<?>, 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" );
}
}

View File

@ -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

View File

@ -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(),

Some files were not shown because too many files have changed in this diff Show More