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:
parent
f86bdf08c1
commit
da22678c74
|
@ -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
|
||||
|
|
|
@ -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() );
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -97,7 +97,7 @@ public abstract class AbstractScrollableResults<R> implements ScrollableResultsI
|
|||
return;
|
||||
}
|
||||
|
||||
rowReader.finishUp( jdbcValuesSourceProcessingState );
|
||||
rowReader.finishUp( rowProcessingState );
|
||||
jdbcValues.finishUp( persistenceContext );
|
||||
|
||||
getPersistenceContext().getJdbcCoordinator().afterStatementExecution();
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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> {
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ public interface LoadingCollectionEntry {
|
|||
/**
|
||||
* The initializer responsible for the loading
|
||||
*/
|
||||
CollectionInitializer getInitializer();
|
||||
CollectionInitializer<?> getInitializer();
|
||||
|
||||
/**
|
||||
* The collection key.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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() };
|
||||
}
|
||||
}
|
|
@ -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() };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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" );
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
|
|
@ -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 )
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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" );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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" );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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" );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue