mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-17 16:44:57 +00:00
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.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 final void makeEntityManaged() {
|
||||
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 final void makeEntityManaged() {
|
||||
getPersister(),
|
||||
isVersionIncrementDisabled
|
||||
);
|
||||
entityHolder.setEntityEntry( entityEntry );
|
||||
if ( isEarlyInsert() ) {
|
||||
addCollectionsByKeyToPersistenceContext( persistenceContextInternal, getState() );
|
||||
}
|
||||
|
@ -16,6 +16,8 @@
|
||||
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 PersistentAttributeInterceptable createEnhancedProxy(EntityKey entityKey,
|
||||
|
||||
// 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 PersistentAttributeInterceptable createEnhancedProxy(EntityKey entityKey,
|
||||
persister,
|
||||
true
|
||||
);
|
||||
entityHolder.setEntityEntry( entityEntry );
|
||||
}
|
||||
|
||||
// inject the interceptor
|
||||
|
@ -12,8 +12,6 @@
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultAssembler;
|
||||
import org.hibernate.sql.results.graph.FetchParentAccess;
|
||||
import org.hibernate.sql.results.graph.InitializerParent;
|
||||
import org.hibernate.sql.results.graph.collection.CollectionInitializer;
|
||||
|
||||
@ -27,75 +25,30 @@
|
||||
@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.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 EntityHolder claimEntityHolderIfPossible(
|
||||
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 EntityHolder claimEntityHolderIfPossible(
|
||||
}
|
||||
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 @@ private void processLoadedEntityHolder(
|
||||
|
||||
@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 EntityEntry addEntity(
|
||||
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 EntityEntry addEntity(
|
||||
persister,
|
||||
disableVersionIncrement
|
||||
);
|
||||
entityHolder.setEntityEntry( entityEntry );
|
||||
return entityEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -685,7 +696,7 @@ public EntityEntry addEntry(
|
||||
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 void addReferenceEntry(
|
||||
entityEntryContext.addEntityEntry( entity, entityEntry );
|
||||
|
||||
setHasNonReadOnlyEnties( status );
|
||||
return entityEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -762,12 +774,15 @@ private void reassociateProxy(LazyInitializer li, HibernateProxy proxy) {
|
||||
.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 Object proxyFor(EntityHolder holder, EntityPersister persister) {
|
||||
|
||||
@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 Object getProxy(EntityKey key) {
|
||||
|
||||
@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 void replaceDelayedEntityIdentityInsertKeys(EntityKey oldKey, Object gene
|
||||
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 void replaceDelayedEntityIdentityInsertKeys(EntityKey oldKey, Object gene
|
||||
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 void replaceEntityEntryRowId(Object entity, Object rowId) {
|
||||
oldEntry.getPersister(),
|
||||
oldEntry.isBeingReplicated()
|
||||
);
|
||||
getEntityHolder( oldEntry.getEntityKey() ).setEntityEntry( entityEntry );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1789,15 +1808,6 @@ public void serialize(ObjectOutputStream oos) throws IOException {
|
||||
|
||||
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 void serialize(ObjectOutputStream oos) throws IOException {
|
||||
} );
|
||||
|
||||
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 static StatefulPersistenceContext deserialize(
|
||||
|
||||
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 static StatefulPersistenceContext deserialize(
|
||||
}
|
||||
}
|
||||
}
|
||||
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 @@ private static class EntityHolderImpl implements EntityHolder, Serializable {
|
||||
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 @@ private EntityHolderImpl(EntityKey entityKey, EntityPersister descriptor, Object
|
||||
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 Object getProxy() {
|
||||
}
|
||||
|
||||
@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 EntityKey(@Nullable Object id, EntityPersister persister) {
|
||||
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 @@ EntityHolder claimEntityHolderIfPossible(
|
||||
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 @@ private StandardRegistrationHandler(
|
||||
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 @@ protected Object performSaveOrReplicate(
|
||||
persister,
|
||||
false
|
||||
);
|
||||
if ( original.getLoadedState() != null ) {
|
||||
persistenceContext.getEntityHolder( key ).setEntityEntry( original );
|
||||
}
|
||||
|
||||
cascadeBeforeSave( source, persister, entity, context );
|
||||
|
||||
|
@ -127,7 +127,7 @@ protected void doEvict(
|
||||
// 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 @@ private static void refresh(RefreshEvent event, RefreshContext refreshedAlready,
|
||||
);
|
||||
|
||||
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 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 @@ private static Object[] readGeneratedValues(
|
||||
null,
|
||||
null,
|
||||
QueryOptions.NONE,
|
||||
true,
|
||||
mappingProducer.resolve(
|
||||
directResultSetAccess,
|
||||
session.getLoadQueryInfluencers(),
|
||||
@ -194,8 +194,7 @@ public boolean shouldReturnProxies() {
|
||||
);
|
||||
|
||||
final RowReader<Object[]> rowReader = ResultsHelper.createRowReader(
|
||||
executionContext,
|
||||
LockOptions.NONE,
|
||||
session.getFactory(),
|
||||
RowTransformerArrayImpl.instance(),
|
||||
Object[].class,
|
||||
jdbcValues
|
||||
|
@ -97,7 +97,7 @@ public final void close() {
|
||||
return;
|
||||
}
|
||||
|
||||
rowReader.finishUp( jdbcValuesSourceProcessingState );
|
||||
rowReader.finishUp( rowProcessingState );
|
||||
jdbcValues.finishUp( persistenceContext );
|
||||
|
||||
getPersistenceContext().getJdbcCoordinator().afterStatementExecution();
|
||||
|
@ -10,8 +10,6 @@
|
||||
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 @@ private boolean prepareCurrentRow() {
|
||||
loadContexts.register( getJdbcValuesSourceProcessingState() );
|
||||
persistenceContext.beforeLoad();
|
||||
try {
|
||||
currentRow = rowReader.readRow( rowProcessingState, getProcessingOptions() );
|
||||
currentRow = rowReader.readRow( rowProcessingState );
|
||||
|
||||
rowProcessingState.finishRowProcessing( true );
|
||||
|
||||
@ -327,7 +325,7 @@ private boolean prepareCurrentRow() {
|
||||
last = false;
|
||||
}
|
||||
else {
|
||||
rowReader.readRow( rowProcessingState, getProcessingOptions() );
|
||||
rowReader.readRow( rowProcessingState );
|
||||
rowProcessingState.finishRowProcessing( false );
|
||||
}
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ private void prepareCurrentRow(boolean underlyingScrollSuccessful) {
|
||||
persistenceContext.beforeLoad();
|
||||
try {
|
||||
try {
|
||||
currentRow = getRowReader().readRow( getRowProcessingState(), getProcessingOptions() );
|
||||
currentRow = getRowReader().readRow( getRowProcessingState() );
|
||||
|
||||
getRowProcessingState().finishRowProcessing( true );
|
||||
getJdbcValuesSourceProcessingState().finishUp( false );
|
||||
|
@ -356,11 +356,15 @@ private void makeEntityCircularReferenceSafe(
|
||||
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 @@ private Object convertCacheEntryToEntity(
|
||||
isReadOnly = source.isDefaultReadOnly();
|
||||
}
|
||||
|
||||
persistenceContext.addEntry(
|
||||
EntityEntry entityEntry = persistenceContext.addEntry(
|
||||
entity,
|
||||
( isReadOnly ? Status.READ_ONLY : Status.MANAGED ),
|
||||
values,
|
||||
@ -483,6 +487,7 @@ private Object convertCacheEntryToEntity(
|
||||
subclassPersister,
|
||||
false
|
||||
);
|
||||
persistenceContext.getEntityHolder( entityKey ).setEntityEntry( entityEntry );
|
||||
subclassPersister.afterInitialize( entity, source );
|
||||
persistenceContext.initializeNonLazyCollections();
|
||||
|
||||
|
@ -43,13 +43,11 @@
|
||||
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 String getResultVariable() {
|
||||
|
||||
@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 JavaType<Object[]> getResultJavaType() {
|
||||
// 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 @@ private AssemblerImpl(
|
||||
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 void resolveState(RowProcessingState rowProcessingState) {
|
||||
}
|
||||
|
||||
@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 <X> void forEachResultAssembler(BiConsumer<Initializer, X> consumer, X ar
|
||||
public JavaType<Object[]> getAssembledJavaType() {
|
||||
return jtd;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -92,7 +92,6 @@
|
||||
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 String getResultVariable() {
|
||||
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 @@
|
||||
|
||||
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 @@
|
||||
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 int getRowSize() {
|
||||
}
|
||||
|
||||
@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.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 ValueExtractor getJdbcValueExtractor() {
|
||||
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.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 EntityResultImpl(
|
||||
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 @@ else if ( entityPersister.storeDiscriminatorInShallowQueryCacheLayout() && discr
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResultAssembler<?> createResultAssembler(
|
||||
FetchParentAccess parentAccess,
|
||||
AssemblerCreationState creationState) {
|
||||
return createResultAssembler( (InitializerParent) parentAccess, creationState );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResultAssembler<?> createResultAssembler(
|
||||
InitializerParent parent,
|
||||
@ -154,20 +146,20 @@ public DomainResultAssembler<?> createResultAssembler(
|
||||
}
|
||||
|
||||
@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 Initializer createInitializer(
|
||||
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 @@ protected FunctionRenderer getFunctionRenderer() {
|
||||
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.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 EntityDiscriminatorMapping getExpressionType() {
|
||||
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 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 String getResultVariable() {
|
||||
|
||||
@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 void collectValueIndexesToCache(BitSet valueIndexes) {
|
||||
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.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 @@ protected List<Object> extractResults(ResultSet resultSet) {
|
||||
null,
|
||||
null,
|
||||
this.context.getQueryOptions(),
|
||||
true,
|
||||
resultSetMapping.resolve( resultSetAccess, context.getSession().getLoadQueryInfluencers(), getSessionFactory() ),
|
||||
null,
|
||||
executionContext
|
||||
@ -203,8 +203,7 @@ protected List<Object> extractResults(ResultSet resultSet) {
|
||||
|
||||
//noinspection unchecked
|
||||
final RowReader<Object> rowReader = (RowReader<Object>) ResultsHelper.createRowReader(
|
||||
executionContext,
|
||||
null,
|
||||
getSessionFactory(),
|
||||
RowTransformerStandardImpl.INSTANCE,
|
||||
null,
|
||||
jdbcValues
|
||||
@ -241,18 +240,18 @@ public boolean shouldReturnProxies() {
|
||||
processingOptions
|
||||
);
|
||||
final ArrayList<Object> results = new ArrayList<>();
|
||||
final RowProcessingStateStandardImpl rowProcessingState = new RowProcessingStateStandardImpl(
|
||||
jdbcValuesSourceProcessingState,
|
||||
executionContext,
|
||||
rowReader,
|
||||
jdbcValues
|
||||
);
|
||||
try {
|
||||
final RowProcessingStateStandardImpl rowProcessingState = new RowProcessingStateStandardImpl(
|
||||
jdbcValuesSourceProcessingState,
|
||||
executionContext,
|
||||
rowReader,
|
||||
jdbcValues
|
||||
);
|
||||
|
||||
rowReader.startLoading( rowProcessingState );
|
||||
|
||||
while ( rowProcessingState.next() ) {
|
||||
results.add( rowReader.readRow( rowProcessingState, processingOptions ) );
|
||||
results.add( rowReader.readRow( rowProcessingState ) );
|
||||
rowProcessingState.finishRowProcessing( true );
|
||||
}
|
||||
if ( resultSetMapping.getNumberOfResultBuilders() == 0
|
||||
@ -267,7 +266,7 @@ public boolean shouldReturnProxies() {
|
||||
return results;
|
||||
}
|
||||
finally {
|
||||
rowReader.finishUp( jdbcValuesSourceProcessingState );
|
||||
rowReader.finishUp( rowProcessingState );
|
||||
jdbcValuesSourceProcessingState.finishUp( results.size() > 1 );
|
||||
}
|
||||
}
|
||||
|
@ -14,21 +14,6 @@
|
||||
* @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 @@ default ColumnReference getColumnReference() {
|
||||
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 @@ default SqlSelection createSqlSelection(
|
||||
);
|
||||
}
|
||||
|
||||
@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 ColumnReference getColumnReference() {
|
||||
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.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 void accept(SqlAstWalker sqlTreeWalker) {
|
||||
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.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 boolean shouldReturnProxies() {
|
||||
);
|
||||
|
||||
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 @@ private <T> int getResultSize(T result) {
|
||||
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 JdbcValues resolveJdbcValuesSource(
|
||||
queryResultsCacheKey,
|
||||
queryIdentifier,
|
||||
executionContext.getQueryOptions(),
|
||||
resultSetAccess.usesFollowOnLocking(),
|
||||
jdbcValuesMapping,
|
||||
metadataForCache,
|
||||
executionContext
|
||||
|
@ -8,37 +8,31 @@
|
||||
|
||||
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 @@
|
||||
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 @@ default void resolveState(RowProcessingState rowProcessingState) {
|
||||
assemble( rowProcessingState );
|
||||
}
|
||||
|
||||
default @Nullable Initializer getInitializer() {
|
||||
default @Nullable Initializer<?> getInitializer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -59,7 +51,8 @@ default void resolveState(RowProcessingState rowProcessingState) {
|
||||
* 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 @@ default boolean containsAnyNonScalarResults() {
|
||||
|
||||
/**
|
||||
* 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 @@ default void collectValueIndexesToCache(BitSet valueIndexes) {
|
||||
}
|
||||
}
|
||||
|
||||
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.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 @@
|
||||
* @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 @@ default void resolveInstance(@Nullable Object instance) {
|
||||
* 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 @@ default void resolveInstance(@Nullable Object instance) {
|
||||
* 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 @@ default void initializeInstanceFromParent(Object parentInstance) {
|
||||
* 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 @@ default boolean isCollectionInitializer() {
|
||||
*
|
||||
* @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 @@ default boolean isCollectionInitializer() {
|
||||
*
|
||||
* @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 @@ default boolean isCollectionInitializer() {
|
||||
*
|
||||
* @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 @@
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface InitializerParent extends Initializer {
|
||||
public interface InitializerParent<Data extends InitializerData> extends Initializer<Data> {
|
||||
|
||||
}
|
||||
|
@ -13,8 +13,8 @@
|
||||
* @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 UnfetchedBasicPartResultAssembler(JavaType<J> javaType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public J assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) {
|
||||
public J assemble(RowProcessingState rowProcessingState) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -27,4 +26,5 @@ public J assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcess
|
||||
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 UnfetchedResultAssembler(JavaType<J> javaType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public J assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) {
|
||||
public J assemble(RowProcessingState rowProcessingState) {
|
||||
return (J) LazyPropertyInitializer.UNFETCHED_PROPERTY;
|
||||
}
|
||||
|
||||
@ -31,5 +30,6 @@ public J assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcess
|
||||
public JavaType<J> getAssembledJavaType() {
|
||||
return javaType;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
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 NavigablePath getNavigablePath() {
|
||||
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.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 DomainResultAssembler<T> getAssembler() {
|
||||
|
||||
@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.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 Object extractRawValue(RowProcessingState rowProcessingState) {
|
||||
|
||||
@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 @@
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface CollectionInitializer extends FetchParentAccess {
|
||||
public interface CollectionInitializer<Data extends InitializerData> extends InitializerParent<Data> {
|
||||
@Override
|
||||
PluralAttributeMapping getInitializedPart();
|
||||
|
||||
@ -30,11 +28,10 @@ default CollectionPersister getInitializingCollectionDescriptor() {
|
||||
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 @@ default boolean isCollectionInitializer() {
|
||||
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.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 @@
|
||||
*
|
||||
* @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;
|
||||
protected @Nullable Object collectionKeyValue;
|
||||
protected @Nullable CollectionKey collectionKey;
|
||||
public static class CollectionInitializerData extends InitializerData {
|
||||
// per-row state
|
||||
protected @Nullable Object collectionKeyValue;
|
||||
protected @Nullable CollectionKey collectionKey;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #AbstractCollectionInitializer(NavigablePath, PluralAttributeMapping, InitializerParent, DomainResult, boolean, AssemblerCreationState)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
protected AbstractCollectionInitializer(
|
||||
NavigablePath collectionPath,
|
||||
PluralAttributeMapping collectionAttributeMapping,
|
||||
FetchParentAccess parent,
|
||||
@Nullable DomainResult<?> collectionKeyResult,
|
||||
boolean isResultInitializer,
|
||||
AssemblerCreationState creationState) {
|
||||
this(
|
||||
collectionPath,
|
||||
collectionAttributeMapping,
|
||||
(InitializerParent) parent,
|
||||
collectionKeyResult,
|
||||
isResultInitializer,
|
||||
creationState
|
||||
);
|
||||
public CollectionInitializerData(RowProcessingState rowProcessingState) {
|
||||
super( rowProcessingState );
|
||||
}
|
||||
|
||||
public @Nullable PersistentCollection<?> getCollectionInstance() {
|
||||
return (PersistentCollection<?>) getInstance();
|
||||
}
|
||||
|
||||
public void setCollectionInstance(@Nullable PersistentCollection<?> collectionInstance) {
|
||||
setInstance( collectionInstance );
|
||||
}
|
||||
}
|
||||
|
||||
protected AbstractCollectionInitializer(
|
||||
NavigablePath collectionPath,
|
||||
PluralAttributeMapping collectionAttributeMapping,
|
||||
InitializerParent parent,
|
||||
InitializerParent<?> parent,
|
||||
@Nullable DomainResult<?> collectionKeyResult,
|
||||
boolean isResultInitializer,
|
||||
AssemblerCreationState creationState) {
|
||||
super( creationState );
|
||||
this.collectionPath = collectionPath;
|
||||
this.collectionAttributeMapping = collectionAttributeMapping;
|
||||
this.isResultInitializer = isResultInitializer;
|
||||
@ -87,58 +82,66 @@ protected AbstractCollectionInitializer(
|
||||
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 @@ protected void resolveCollectionKey(RowProcessingState rowProcessingState, boole
|
||||
// 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 void resolveInstance(Object instance, RowProcessingState rowProcessingSta
|
||||
// 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 void resolveInstance(Object instance, RowProcessingState rowProcessingSta
|
||||
}
|
||||
|
||||
@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 PluralAttributeMapping getInitializedPart() {
|
||||
}
|
||||
|
||||
@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 boolean isPartOfKey() {
|
||||
public boolean isResultInitializer() {
|
||||
return isResultInitializer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable CollectionKey resolveCollectionKey(RowProcessingState rowProcessingState) {
|
||||
resolveInstance();
|
||||
return collectionKey;
|
||||
}
|
||||
}
|
||||
|
@ -20,23 +20,19 @@
|
||||
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 @@
|
||||
* @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;
|
||||
/**
|
||||
* The value of the collection side of the collection key (FK). Identifies
|
||||
* inclusion in the collection. Can be null to indicate that the current row
|
||||
* does not contain any collection values
|
||||
*/
|
||||
protected Object collectionValueKey;
|
||||
protected LoadingCollectionEntryImpl responsibility;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #AbstractImmediateCollectionInitializer(NavigablePath, PluralAttributeMapping, InitializerParent, LockMode, DomainResult, DomainResult, boolean, AssemblerCreationState)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public AbstractImmediateCollectionInitializer(
|
||||
NavigablePath collectionPath,
|
||||
PluralAttributeMapping collectionAttributeMapping,
|
||||
FetchParentAccess parentAccess,
|
||||
LockMode lockMode,
|
||||
DomainResult<?> collectionKeyResult,
|
||||
DomainResult<?> collectionValueKeyResult,
|
||||
boolean isResultInitializer,
|
||||
AssemblerCreationState creationState) {
|
||||
this(
|
||||
collectionPath,
|
||||
collectionAttributeMapping,
|
||||
(InitializerParent) parentAccess,
|
||||
lockMode,
|
||||
collectionKeyResult,
|
||||
collectionValueKeyResult,
|
||||
isResultInitializer,
|
||||
creationState
|
||||
);
|
||||
public ImmediateCollectionInitializerData(RowProcessingState rowProcessingState) {
|
||||
super( rowProcessingState );
|
||||
}
|
||||
}
|
||||
|
||||
public AbstractImmediateCollectionInitializer(
|
||||
NavigablePath collectionPath,
|
||||
PluralAttributeMapping collectionAttributeMapping,
|
||||
InitializerParent parent,
|
||||
InitializerParent<?> parent,
|
||||
LockMode lockMode,
|
||||
DomainResult<?> collectionKeyResult,
|
||||
DomainResult<?> collectionValueKeyResult,
|
||||
@ -108,47 +85,54 @@ public AbstractImmediateCollectionInitializer(
|
||||
);
|
||||
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 void resolveKey() {
|
||||
/**
|
||||
* 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 )
|
||||
);
|
||||
}
|
||||
state = State.INITIALIZED;
|
||||
if ( data.getCollectionInstance().wasInitialized() ) {
|
||||
data.setState( State.INITIALIZED );
|
||||
}
|
||||
else if ( !shallowCached ) {
|
||||
takeResponsibility( rowProcessingState, collectionKey );
|
||||
else if ( !data.shallowCached ) {
|
||||
takeResponsibility( data );
|
||||
}
|
||||
}
|
||||
else if ( ( existingUnowned = persistenceContext.useUnownedCollection( collectionKey ) ) != null ) {
|
||||
collectionInstance = existingUnowned;
|
||||
else if ( ( existingUnowned = persistenceContext.useUnownedCollection( data.collectionKey ) ) != null ) {
|
||||
data.setCollectionInstance( existingUnowned );
|
||||
|
||||
// we found the corresponding collection instance as unowned on the Session. If
|
||||
// it is already initialized we have nothing to do
|
||||
|
||||
if ( collectionInstance.wasInitialized() ) {
|
||||
if ( CollectionLoadingLogger.COLL_LOAD_LOGGER.isDebugEnabled() ) {
|
||||
COLL_LOAD_LOGGER.debugf(
|
||||
"(%s) Found existing unowned collection instance [%s] in Session; skipping processing - [%s]",
|
||||
getSimpleConcreteImplName(),
|
||||
LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() ),
|
||||
toLoggableString( collectionInstance )
|
||||
);
|
||||
}
|
||||
state = State.INITIALIZED;
|
||||
if ( data.getCollectionInstance().wasInitialized() ) {
|
||||
data.setState( State.INITIALIZED );
|
||||
}
|
||||
else if ( !shallowCached ) {
|
||||
takeResponsibility( rowProcessingState, collectionKey );
|
||||
else if ( !data.shallowCached ) {
|
||||
takeResponsibility( data );
|
||||
}
|
||||
}
|
||||
else {
|
||||
final CollectionPersister collectionDescriptor = getCollectionAttributeMapping().getCollectionDescriptor();
|
||||
final CollectionSemantics<?, ?> collectionSemantics = collectionDescriptor.getCollectionSemantics();
|
||||
|
||||
collectionInstance = collectionSemantics.instantiateWrapper(
|
||||
collectionKey.getKey(),
|
||||
data.setCollectionInstance( collectionSemantics.instantiateWrapper(
|
||||
data.collectionKey.getKey(),
|
||||
getInitializingCollectionDescriptor(),
|
||||
session
|
||||
);
|
||||
|
||||
if ( CollectionLoadingLogger.COLL_LOAD_LOGGER.isDebugEnabled() ) {
|
||||
COLL_LOAD_LOGGER.debugf(
|
||||
"(%s) Created new collection wrapper [%s] : %s",
|
||||
getSimpleConcreteImplName(),
|
||||
LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() ),
|
||||
toLoggableString( collectionInstance )
|
||||
);
|
||||
}
|
||||
) );
|
||||
|
||||
if ( owningEntityInitializer != null ) {
|
||||
assert owningEntityInitializer.getTargetInstance() != null;
|
||||
collectionInstance.setOwner( owningEntityInitializer.getTargetInstance() );
|
||||
assert owningEntityInitializer.getTargetInstance( rowProcessingState ) != null;
|
||||
data.getCollectionInstance().setOwner( owningEntityInitializer.getTargetInstance( rowProcessingState ) );
|
||||
}
|
||||
|
||||
persistenceContext.addUninitializedCollection(
|
||||
collectionDescriptor,
|
||||
collectionInstance,
|
||||
collectionKey.getKey()
|
||||
data.getCollectionInstance(),
|
||||
data.collectionKey.getKey()
|
||||
);
|
||||
|
||||
if ( !shallowCached ) {
|
||||
takeResponsibility( rowProcessingState, collectionKey );
|
||||
if ( !data.shallowCached ) {
|
||||
takeResponsibility( data );
|
||||
}
|
||||
}
|
||||
|
||||
if ( responsibility != null ) {
|
||||
if ( CollectionLoadingLogger.COLL_LOAD_LOGGER.isDebugEnabled() ) {
|
||||
COLL_LOAD_LOGGER.debugf(
|
||||
"(%s) Responsible for loading collection [%s] : %s",
|
||||
getSimpleConcreteImplName(),
|
||||
LoggingHelper.toLoggableString( getNavigablePath(), collectionKey.getKey() ),
|
||||
toLoggableString( collectionInstance )
|
||||
);
|
||||
}
|
||||
}
|
||||
if ( shallowCached ) {
|
||||
assert responsibility == null;
|
||||
initializeShallowCached( rowProcessingState );
|
||||
if ( data.shallowCached ) {
|
||||
assert data.responsibility == null;
|
||||
initializeShallowCached( data );
|
||||
}
|
||||
}
|
||||
|
||||
protected void initializeShallowCached(RowProcessingState rowProcessingState) {
|
||||
assert shallowCached;
|
||||
final PersistenceContext persistenceContext = rowProcessingState.getSession()
|
||||
protected void initializeShallowCached(Data data) {
|
||||
assert data.shallowCached;
|
||||
final PersistenceContext persistenceContext = data.getRowProcessingState().getSession()
|
||||
.getPersistenceContextInternal();
|
||||
// If this is a query cache hit with the shallow query cache layout,
|
||||
// we have to lazy load the collection instead
|
||||
collectionInstance.forceInitialization();
|
||||
data.getCollectionInstance().forceInitialization();
|
||||
if ( collectionAttributeMapping.getCollectionDescriptor()
|
||||
.getCollectionSemantics()
|
||||
.getCollectionClassification() == CollectionClassification.ARRAY ) {
|
||||
persistenceContext.addCollectionHolder( collectionInstance );
|
||||
persistenceContext.addCollectionHolder( data.getCollectionInstance() );
|
||||
}
|
||||
state = State.INITIALIZED;
|
||||
initializeSubInstancesFromParent( rowProcessingState );
|
||||
data.setState( State.INITIALIZED );
|
||||
initializeSubInstancesFromParent( data );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setMissing() {
|
||||
super.setMissing();
|
||||
collectionValueKey = null;
|
||||
responsibility = null;
|
||||
protected void setMissing(Data data) {
|
||||
super.setMissing( data );
|
||||
data.collectionValueKey = null;
|
||||
data.responsibility = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolveInstance(Object instance) {
|
||||
assert state == State.UNINITIALIZED;
|
||||
public void resolveInstance(Object instance, Data data) {
|
||||
assert data.getState() == State.UNINITIALIZED || instance == data.getCollectionInstance();
|
||||
if ( instance == null ) {
|
||||
setMissing();
|
||||
setMissing( data );
|
||||
return;
|
||||
}
|
||||
final RowProcessingState rowProcessingState = data.getRowProcessingState();
|
||||
// Check if the given instance is different from the previous row state to avoid creating CollectionKey
|
||||
if ( collectionInstance != instance ) {
|
||||
if ( data.getCollectionInstance() != instance ) {
|
||||
final PersistenceContext persistenceContext = rowProcessingState.getSession().getPersistenceContextInternal();
|
||||
final PersistentCollection<?> persistentCollection;
|
||||
if ( collectionAttributeMapping.getCollectionDescriptor()
|
||||
@ -397,21 +319,21 @@ public void resolveInstance(Object instance) {
|
||||
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 void resolveInstance(Object instance) {
|
||||
}
|
||||
}
|
||||
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 void resolveInstance(Object instance) {
|
||||
}
|
||||
}
|
||||
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 @@ private String toLoggableString(PersistentCollection<?> collectionInstance) {
|
||||
: 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 @@ protected abstract void readCollectionRow(
|
||||
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.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 @@
|
||||
/**
|
||||
* @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 ArrayInitializer(
|
||||
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 @@ protected String getSimpleConcreteImplName() {
|
||||
}
|
||||
|
||||
@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 @@ protected void readCollectionRow(
|
||||
}
|
||||
|
||||
@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.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 ArrayInitializerProducer(
|
||||
}
|
||||
|
||||
@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.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 @@
|
||||
*
|
||||
* @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 BagInitializer(
|
||||
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 @@ protected String getSimpleConcreteImplName() {
|
||||
}
|
||||
|
||||
@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 @@ protected void readCollectionRow(
|
||||
}
|
||||
|
||||
@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.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 BagInitializerProducer(
|
||||
}
|
||||
|
||||
@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.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 @@
|
||||
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 JavaType<?> getAssembledJavaType() {
|
||||
}
|
||||
|
||||
@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.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 JavaType<?> getResultJavaType() {
|
||||
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 DomainResultAssembler createResultAssembler(
|
||||
}
|
||||
|
||||
@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.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 boolean containsCollectionFetches() {
|
||||
|
||||
@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 DomainResultAssembler<?> createAssembler(
|
||||
}
|
||||
|
||||
@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.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 DelayedCollectionFetch(
|
||||
|
||||
@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 DomainResultAssembler<?> createAssembler(
|
||||
}
|
||||
}
|
||||
|
||||
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.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 NavigablePath resolveNavigablePath(Fetchable fetchable) {
|
||||
}
|
||||
|
||||
@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.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 @@
|
||||
*
|
||||
* @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 ListInitializer(
|
||||
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 @@ protected String getSimpleConcreteImplName() {
|
||||
}
|
||||
|
||||
@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 @@ protected void readCollectionRow(
|
||||
}
|
||||
|
||||
@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.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 ListInitializerProducer(
|
||||
}
|
||||
|
||||
@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.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 @@
|
||||
*
|
||||
* @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 MapInitializer(
|
||||
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 @@ protected String getSimpleConcreteImplName() {
|
||||
}
|
||||
|
||||
@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 @@ protected void readCollectionRow(
|
||||
}
|
||||
|
||||
@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.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 MapInitializerProducer(
|
||||
}
|
||||
|
||||
@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 boolean hasTableGroup() {
|
||||
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.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 @@
|
||||
/**
|
||||
* @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.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 @@
|
||||
/**
|
||||
* @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 SetInitializer(
|
||||
isResultInitializer,
|
||||
creationState
|
||||
);
|
||||
this.elementAssembler = elementFetch.createAssembler( (InitializerParent) this, creationState );
|
||||
this.elementAssembler = elementFetch.createAssembler( this, creationState );
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -90,17 +63,17 @@ protected String getSimpleConcreteImplName() {
|
||||
}
|
||||
|
||||
@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 @@ protected void readCollectionRow(
|
||||
}
|
||||
|
||||
@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.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 SetInitializerProducer(
|
||||
}
|
||||
|
||||
@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 @@
|
||||
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 UnfetchedCollectionAssembler(PluralAttributeMapping fetchedMapping) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) {
|
||||
public Object assemble(RowProcessingState rowProcessingState) {
|
||||
return LazyPropertyInitializer.UNFETCHED_PROPERTY;
|
||||
}
|
||||
|
||||
@ -30,4 +29,5 @@ public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourcePr
|
||||
public JavaType getAssembledJavaType() {
|
||||
return fetchedMapping.getJavaType();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
|
||||
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 @@
|
||||
*
|
||||
* @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.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 EmbeddableMappingType getReferencedMappingType() {
|
||||
|
||||
@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.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 @@
|
||||
* 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 AggregateEmbeddableInitializerImpl(
|
||||
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 @@ protected DomainResultAssembler<?>[][] createAssemblers(
|
||||
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.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 EmbeddableValuedModelPart getReferencedMappingContainer() {
|
||||
|
||||
@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 @@
|
||||
|
||||
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 @@
|
||||
* @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 JavaType getAssembledJavaType() {
|
||||
}
|
||||
|
||||
@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 void resolveState(RowProcessingState rowProcessingState) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmbeddableInitializer getInitializer() {
|
||||
public EmbeddableInitializer<?> getInitializer() {
|
||||
return initializer;
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,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.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 EmbeddableValuedModelPart getReferencedMappingContainer() {
|
||||
|
||||
@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 @@
|
||||
|
||||
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.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 EmbeddableMappingType getReferencedMappingType() {
|
||||
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.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 Fetch generateFetchableFetch(
|
||||
|
||||
@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 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.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 @@
|
||||
/**
|
||||
* @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;
|
||||
protected EmbeddableMappingType.ConcreteEmbeddableType concreteEmbeddableType;
|
||||
public static class EmbeddableInitializerData extends InitializerData implements ValueAccess {
|
||||
protected final InitializerData parentData;
|
||||
protected final Object[] rowState;
|
||||
protected EmbeddableMappingType.ConcreteEmbeddableType concreteEmbeddableType;
|
||||
|
||||
public EmbeddableInitializerData(EmbeddableInitializerImpl initializer, RowProcessingState rowProcessingState) {
|
||||
super( rowProcessingState );
|
||||
this.parentData = initializer.parent == null ? null : initializer.parent.getData( rowProcessingState );
|
||||
final EmbeddableMappingType embeddableTypeDescriptor = initializer.embedded.getEmbeddableTypeDescriptor();
|
||||
final int size = embeddableTypeDescriptor.getNumberOfFetchables();
|
||||
this.rowState = new Object[ size ];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getValues() {
|
||||
return getState() == State.MISSING ? null : rowState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> 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 @@ protected DomainResultAssembler<?>[][] createAssemblers(
|
||||
|
||||
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 @@ protected DomainResultAssembler<?>[][] createAssemblers(
|
||||
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 @@ protected static Initializer[][] createInitializers(DomainResultAssembler<?>[][]
|
||||
subInitializers[i] = Initializer.EMPTY_ARRAY;
|
||||
}
|
||||
}
|
||||
return subInitializers;
|
||||
//noinspection unchecked
|
||||
return (Initializer<InitializerData>[][]) subInitializers;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -163,12 +189,7 @@ public EmbeddableValuedModelPart getInitializedPart() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable FetchParentAccess getFetchParentAccess() {
|
||||
return (FetchParentAccess) parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable InitializerParent getParent() {
|
||||
public @Nullable InitializerParent<?> getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
@ -183,8 +204,9 @@ public boolean isResultInitializer() {
|
||||
}
|
||||
|
||||
@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 boolean isPartOfKey() {
|
||||
}
|
||||
|
||||
@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 void resolveInstance(@Nullable Object instance) {
|
||||
}
|
||||
|
||||
@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 void initializeInstance() {
|
||||
// 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 @@ else if ( isPartOfKey ) {
|
||||
}
|
||||
}
|
||||
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 @@ private Object createCompositeInstance() {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ private Initializer determineOwningInitializer() {
|
||||
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.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 EmbeddableValuedModelPart getReferencedMappingContainer() {
|
||||
|
||||
@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.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 NestedRowProcessingState(
|
||||
}
|
||||
|
||||
public static NestedRowProcessingState wrap(
|
||||
AggregateEmbeddableInitializer aggregateEmbeddableInitializer,
|
||||
AggregateEmbeddableInitializerImpl aggregateEmbeddableInitializer,
|
||||
RowProcessingState processingState) {
|
||||
if ( processingState instanceof NestedRowProcessingState ) {
|
||||
return new NestedRowProcessingState(
|
||||
@ -56,11 +58,31 @@ public RowProcessingState unwrap() {
|
||||
|
||||
// -- 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 boolean isQueryCacheHit() {
|
||||
return processingState.isQueryCacheHit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishRowProcessing() {
|
||||
processingState.finishRowProcessing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishRowProcessing(boolean wasAdded) {
|
||||
processingState.finishRowProcessing( wasAdded );
|
||||
|
@ -31,7 +31,7 @@ public NonAggregatedIdentifierMappingFetch(EmbeddableFetchImpl original) {
|
||||
}
|
||||
|
||||
@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.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 @@
|
||||
/**
|
||||
* @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 NonAggregatedIdentifierMappingInitializer(
|
||||
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 EmbeddableValuedModelPart getInitializedPart() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable FetchParentAccess getFetchParentAccess() {
|
||||
return (FetchParentAccess) parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable InitializerParent getParent() {
|
||||
public @Nullable InitializerParent<?> getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
@ -143,27 +162,35 @@ public boolean isResultInitializer() {
|
||||
}
|
||||
|
||||
@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 void resolveKey() {
|
||||
}
|
||||
|
||||
@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 void resolveInstance(@Nullable Object instance) {
|
||||
}
|
||||
|
||||
@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 void initializeInstance() {
|
||||
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 @@ private void extractRowState() {
|
||||
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 @@ private void extractRowState() {
|
||||
|
||||
@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 NonAggregatedIdentifierMappingResult(
|
||||
}
|
||||
|
||||
@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 @@
|
||||
|
||||
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 @@
|
||||
*
|
||||
* @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 @@ default boolean isEntityInitializer() {
|
||||
}
|
||||
|
||||
@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;
|
||||
|
||||
// per-row state
|
||||
protected @Nullable Object initializedEntityInstance;
|
||||
protected @Nullable Object entityIdentifier;
|
||||
protected @Nullable EntityKey entityKey;
|
||||
public static abstract class AbstractBatchEntitySelectFetchInitializerData extends EntitySelectFetchInitializerData {
|
||||
// per-row state
|
||||
protected @Nullable EntityKey entityKey;
|
||||
|
||||
/**
|
||||
*
|
||||
* @deprecated Use {@link #AbstractBatchEntitySelectFetchInitializer(InitializerParent, ToOneAttributeMapping, NavigablePath, EntityPersister, DomainResultAssembler)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public AbstractBatchEntitySelectFetchInitializer(
|
||||
FetchParentAccess parent,
|
||||
ToOneAttributeMapping referencedModelPart,
|
||||
NavigablePath fetchedNavigable,
|
||||
EntityPersister concreteDescriptor,
|
||||
DomainResultAssembler<?> identifierAssembler) {
|
||||
this(
|
||||
(InitializerParent) parent,
|
||||
referencedModelPart,
|
||||
fetchedNavigable,
|
||||
concreteDescriptor,
|
||||
identifierAssembler
|
||||
);
|
||||
public AbstractBatchEntitySelectFetchInitializerData(RowProcessingState rowProcessingState) {
|
||||
super( rowProcessingState );
|
||||
}
|
||||
}
|
||||
|
||||
public AbstractBatchEntitySelectFetchInitializer(
|
||||
InitializerParent parent,
|
||||
ToOneAttributeMapping referencedModelPart,
|
||||
InitializerParent<?> parent,
|
||||
ToOneAttributeMapping toOneMapping,
|
||||
NavigablePath fetchedNavigable,
|
||||
EntityPersister concreteDescriptor,
|
||||
DomainResultAssembler<?> identifierAssembler) {
|
||||
this.parent = parent;
|
||||
this.referencedModelPart = referencedModelPart;
|
||||
this.navigablePath = fetchedNavigable;
|
||||
this.isPartOfKey = Initializer.isPartOfKey( fetchedNavigable, parent );
|
||||
this.concreteDescriptor = concreteDescriptor;
|
||||
this.identifierAssembler = identifierAssembler;
|
||||
this.owningEntityInitializer = Initializer.findOwningEntityInitializer( parent );
|
||||
DomainResult<?> keyResult,
|
||||
AssemblerCreationState creationState) {
|
||||
super( parent, toOneMapping, fetchedNavigable, concreteDescriptor, keyResult, creationState );
|
||||
//noinspection unchecked
|
||||
this.owningEntityInitializer = (EntityInitializer<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 ) {
|
||||
// need to add the key to the batch queue only when the entity has not been already loaded or
|
||||
// there isn't another initializer that is loading it
|
||||
registerToBatchFetchQueue( rowProcessingState );
|
||||
if ( batchDisabled ) {
|
||||
initialize( data );
|
||||
}
|
||||
else {
|
||||
data.entityKey = new EntityKey( data.entityIdentifier, concreteDescriptor );
|
||||
data.setInstance( getExistingInitializedInstance( data ) );
|
||||
if ( data.getInstance() == null ) {
|
||||
// need to add the key to the batch queue only when the entity has not been already loaded or
|
||||
// there isn't another initializer that is loading it
|
||||
registerToBatchFetchQueue( data );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolveInstance(Object instance) {
|
||||
public void resolveInstance(Object instance, Data data) {
|
||||
if ( instance == null ) {
|
||||
state = State.MISSING;
|
||||
entityKey = null;
|
||||
initializedEntityInstance = null;
|
||||
data.setState( State.MISSING );
|
||||
data.entityKey = null;
|
||||
data.setInstance( null );
|
||||
return;
|
||||
}
|
||||
final Initializer initializer = identifierAssembler.getInitializer();
|
||||
final RowProcessingState rowProcessingState = data.getRowProcessingState();
|
||||
final Initializer<?> initializer = keyAssembler.getInitializer();
|
||||
// Only need to extract the identifier if the identifier has a many to one
|
||||
final boolean hasKeyManyToOne = initializer != null;
|
||||
final SharedSessionContractImplementor session = rowProcessingState.getSession();
|
||||
final LazyInitializer lazyInitializer = extractLazyInitializer( instance );
|
||||
entityKey = null;
|
||||
data.entityKey = null;
|
||||
if ( lazyInitializer == null ) {
|
||||
// Entity is initialized
|
||||
state = State.INITIALIZED;
|
||||
data.setState( State.INITIALIZED );
|
||||
if ( hasKeyManyToOne ) {
|
||||
entityIdentifier = concreteDescriptor.getIdentifier( instance, session );
|
||||
data.entityIdentifier = concreteDescriptor.getIdentifier( instance, rowProcessingState.getSession() );
|
||||
}
|
||||
initializedEntityInstance = instance;
|
||||
data.setInstance( instance );
|
||||
}
|
||||
else if ( lazyInitializer.isUninitialized() ) {
|
||||
state = State.RESOLVED;
|
||||
data.setState( State.RESOLVED );
|
||||
if ( hasKeyManyToOne ) {
|
||||
entityIdentifier = lazyInitializer.getIdentifier();
|
||||
data.entityIdentifier = lazyInitializer.getIdentifier();
|
||||
}
|
||||
// Resolve and potentially create the entity instance
|
||||
registerToBatchFetchQueue( rowProcessingState );
|
||||
registerToBatchFetchQueue( data );
|
||||
}
|
||||
else {
|
||||
// Entity is initialized
|
||||
state = State.INITIALIZED;
|
||||
data.setState( State.INITIALIZED );
|
||||
if ( hasKeyManyToOne ) {
|
||||
entityIdentifier = lazyInitializer.getIdentifier();
|
||||
data.entityIdentifier = lazyInitializer.getIdentifier();
|
||||
}
|
||||
initializedEntityInstance = lazyInitializer.getImplementation();
|
||||
data.setInstance( lazyInitializer.getImplementation() );
|
||||
}
|
||||
if ( hasKeyManyToOne ) {
|
||||
initializer.resolveInstance( entityIdentifier );
|
||||
initializer.resolveInstance( data.entityIdentifier, rowProcessingState );
|
||||
}
|
||||
else if ( !rowProcessingState.isQueryCacheHit() && rowProcessingState.getQueryOptions().isResultCachingEnabled() == Boolean.TRUE ) {
|
||||
else if ( rowProcessingState.needsResolveState() ) {
|
||||
// Resolve the state of the identifier if result caching is enabled and this is not a query cache hit
|
||||
identifierAssembler.resolveState( rowProcessingState );
|
||||
keyAssembler.resolveState( rowProcessingState );
|
||||
}
|
||||
}
|
||||
|
||||
protected Object getExistingInitializedInstance(RowProcessingState rowProcessingState) {
|
||||
final SharedSessionContractImplementor session = rowProcessingState.getSession();
|
||||
@Override
|
||||
public void initializeInstance(Data data) {
|
||||
if ( data.getState() != State.RESOLVED ) {
|
||||
return;
|
||||
}
|
||||
data.setState( State.INITIALIZED );
|
||||
if ( batchDisabled ) {
|
||||
Hibernate.initialize( data.getInstance() );
|
||||
}
|
||||
}
|
||||
|
||||
protected Object getExistingInitializedInstance(Data data) {
|
||||
final SharedSessionContractImplementor session = data.getRowProcessingState().getSession();
|
||||
final PersistenceContext persistenceContext = session.getPersistenceContext();
|
||||
final EntityHolder holder = persistenceContext.getEntityHolder( entityKey );
|
||||
final EntityHolder holder = persistenceContext.getEntityHolder( data.entityKey );
|
||||
if ( holder != null && holder.getEntity() != null && holder.isEventuallyInitialized() ) {
|
||||
return holder.getEntity();
|
||||
}
|
||||
// we need to register a resolution listener only if there is not an already initialized instance
|
||||
// or an instance that another initializer is loading
|
||||
registerResolutionListener();
|
||||
registerResolutionListener( data );
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void registerToBatchFetchQueue(RowProcessingState rowProcessingState) {
|
||||
assert entityKey != null;
|
||||
rowProcessingState.getSession().getPersistenceContext()
|
||||
.getBatchFetchQueue().addBatchLoadableEntityKey( entityKey );
|
||||
protected void registerToBatchFetchQueue(Data data) {
|
||||
assert data.entityKey != null;
|
||||
data.getRowProcessingState().getSession().getPersistenceContext()
|
||||
.getBatchFetchQueue().addBatchLoadableEntityKey( data.entityKey );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeInstanceFromParent(Object parentInstance) {
|
||||
public void initializeInstanceFromParent(Object parentInstance, Data data) {
|
||||
final AttributeMapping attributeMapping = getInitializedPart().asAttributeMapping();
|
||||
final Object instance = attributeMapping != null
|
||||
? attributeMapping.getValue( parentInstance )
|
||||
: parentInstance;
|
||||
// No need to initialize these fields
|
||||
entityKey = null;
|
||||
initializedEntityInstance = null;
|
||||
data.entityKey = null;
|
||||
data.setInstance( null );
|
||||
if ( instance == null ) {
|
||||
state = State.MISSING;
|
||||
data.setState( State.MISSING );
|
||||
}
|
||||
else {
|
||||
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( instance );
|
||||
if ( lazyInitializer != null && lazyInitializer.isUninitialized() ) {
|
||||
entityKey = new EntityKey( lazyInitializer.getIdentifier(), concreteDescriptor );
|
||||
registerToBatchFetchQueue( rowProcessingState );
|
||||
data.entityKey = new EntityKey( lazyInitializer.getIdentifier(), concreteDescriptor );
|
||||
registerToBatchFetchQueue( data );
|
||||
}
|
||||
state = State.INITIALIZED;
|
||||
data.setState( State.INITIALIZED );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <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 @@ protected AttributeMapping[] getParentEntityAttributes(String attributeName) {
|
||||
];
|
||||
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 @@ protected static AttributeMapping getParentEntityAttribute(
|
||||
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.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 boolean isSelectByUniqueKey() {
|
||||
|
||||
@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.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 Object readResolve() {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @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 BatchEntityInsideEmbeddableSelectFetchInitializer(
|
||||
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 @@ protected void initializeAttributeType(Type[] attributeTypes, EntityPersister en
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerToBatchFetchQueue(RowProcessingState rowProcessingState) {
|
||||
super.registerToBatchFetchQueue( rowProcessingState );
|
||||
initializedEntityInstance = BATCH_PROPERTY;
|
||||
protected void registerToBatchFetchQueue(BatchEntityInsideEmbeddableSelectFetchInitializerData data) {
|
||||
super.registerToBatchFetchQueue( data );
|
||||
data.setInstance( BATCH_PROPERTY );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeInstance() {
|
||||
super.initializeInstance();
|
||||
public void initializeInstance(BatchEntityInsideEmbeddableSelectFetchInitializerData data) {
|
||||
super.initializeInstance( data );
|
||||
// todo: check why this can't be moved to #registerToBatchFetchQueue
|
||||
if ( initializedEntityInstance == BATCH_PROPERTY ) {
|
||||
final int owningEntitySubclassId = owningEntityInitializer.getConcreteDescriptor().getSubclassId();
|
||||
if ( data.getInstance() == BATCH_PROPERTY ) {
|
||||
final RowProcessingState rowProcessingState = data.getRowProcessingState();
|
||||
final InitializerData owningData = owningEntityInitializer.getData( rowProcessingState );
|
||||
final int owningEntitySubclassId = owningEntityInitializer.getConcreteDescriptor( owningData ).getSubclassId();
|
||||
final AttributeMapping rootEmbeddableAttribute = rootEmbeddableAttributes[owningEntitySubclassId];
|
||||
if ( rootEmbeddableAttribute != null ) {
|
||||
getParentInfos().add( new ParentInfo(
|
||||
owningEntityInitializer.getTargetInstance(),
|
||||
parent.getInitializedInstance(),
|
||||
rootEmbeddableAttribute.getStateArrayPosition(),
|
||||
owningEntitySubclassId
|
||||
) );
|
||||
if ( data.toBatchLoad == null ) {
|
||||
data.toBatchLoad = new HashMap<>();
|
||||
}
|
||||
data.toBatchLoad.computeIfAbsent( data.entityKey, key -> new ArrayList<>() ).add(
|
||||
new ParentInfo(
|
||||
owningEntityInitializer.getTargetInstance( owningData ),
|
||||
parent.getResolvedInstance( rowProcessingState ),
|
||||
rootEmbeddableAttribute.getStateArrayPosition(),
|
||||
owningEntitySubclassId
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerResolutionListener() {
|
||||
}
|
||||
|
||||
private List<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 ParentInfo(
|
||||
}
|
||||
|
||||
@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 void endLoading(ExecutionContext executionContext) {
|
||||
}
|
||||
}
|
||||
);
|
||||
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,70 +20,64 @@
|
||||
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;
|
||||
|
||||
private Map<EntityKey, List<ParentInfo>> toBatchLoad;
|
||||
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 {
|
||||
private final Object parentInstance;
|
||||
private final int propertyIndex;
|
||||
@ -95,13 +89,13 @@ public ParentInfo(Object parentInstance, int propertyIndex) {
|
||||
}
|
||||
|
||||
@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 void endLoading(ExecutionContext executionContext) {
|
||||
}
|
||||
}
|
||||
);
|
||||
toBatchLoad.clear();
|
||||
data.toBatchLoad.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,9 +15,9 @@
|
||||
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 @@
|
||||
* 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> {
|
||||
|
||||
private final Set<EntityKey> toBatchLoad = new HashSet<>();
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endLoading(ExecutionContext executionContext) {
|
||||
super.endLoading( executionContext );
|
||||
final SharedSessionContractImplementor session = executionContext.getSession();
|
||||
for ( EntityKey key : toBatchLoad ) {
|
||||
loadInstance( key, referencedModelPart, session );
|
||||
public void endLoading(BatchInitializeEntitySelectFetchInitializerData data) {
|
||||
super.endLoading( data );
|
||||
final SharedSessionContractImplementor session = data.getRowProcessingState().getSession();
|
||||
for ( EntityKey key : data.toBatchLoad ) {
|
||||
loadInstance( key, toOneMapping, session );
|
||||
}
|
||||
toBatchLoad.clear();
|
||||
data.toBatchLoad.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -14,7 +14,6 @@
|
||||
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 boolean hasTableGroup() {
|
||||
|
||||
@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 DomainResultAssembler<?> createAssembler(
|
||||
}
|
||||
|
||||
@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.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.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 @@
|
||||
/**
|
||||
* 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
|
||||
protected EntityPersister concreteDescriptor;
|
||||
protected Object entityIdentifier;
|
||||
protected Object entityInstance;
|
||||
public static class DiscriminatedEntityInitializerData extends InitializerData {
|
||||
protected EntityPersister concreteDescriptor;
|
||||
protected Object entityIdentifier;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #DiscriminatedEntityInitializer(InitializerParent, DiscriminatedAssociationModelPart, NavigablePath, Fetch, Fetch, boolean, boolean, AssemblerCreationState)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public DiscriminatedEntityInitializer(
|
||||
FetchParentAccess parent,
|
||||
DiscriminatedAssociationModelPart fetchedPart,
|
||||
NavigablePath fetchedNavigable,
|
||||
Fetch discriminatorFetch,
|
||||
Fetch keyFetch,
|
||||
boolean eager,
|
||||
boolean resultInitializer,
|
||||
AssemblerCreationState creationState) {
|
||||
this(
|
||||
(InitializerParent) parent,
|
||||
fetchedPart,
|
||||
fetchedNavigable,
|
||||
discriminatorFetch,
|
||||
keyFetch,
|
||||
eager,
|
||||
resultInitializer,
|
||||
creationState
|
||||
);
|
||||
public DiscriminatedEntityInitializerData(RowProcessingState rowProcessingState) {
|
||||
super( rowProcessingState );
|
||||
}
|
||||
}
|
||||
|
||||
public DiscriminatedEntityInitializer(
|
||||
InitializerParent parent,
|
||||
InitializerParent<?> parent,
|
||||
DiscriminatedAssociationModelPart fetchedPart,
|
||||
NavigablePath fetchedNavigable,
|
||||
Fetch discriminatorFetch,
|
||||
@ -91,23 +71,24 @@ public DiscriminatedEntityInitializer(
|
||||
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 NavigablePath getNavigablePath() {
|
||||
}
|
||||
|
||||
@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 @@ else if ( !rowProcessingState.isQueryCacheHit() && rowProcessingState.getQueryOp
|
||||
}
|
||||
|
||||
@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 void initializeInstanceFromParent(Object parentInstance) {
|
||||
}
|
||||
|
||||
@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 String toString() {
|
||||
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.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 String getResultVariable() {
|
||||
|
||||
@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 DomainResultAssembler<T> createResultAssembler(
|
||||
}
|
||||
|
||||
@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 @@
|
||||
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 @@
|
||||
*/
|
||||
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 JavaType getAssembledJavaType() {
|
||||
}
|
||||
|
||||
@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.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 FetchTiming getTiming() {
|
||||
}
|
||||
|
||||
@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.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 @@
|
||||
* @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;
|
||||
|
||||
// per-row state
|
||||
private Object entityInstance;
|
||||
private Object identifier;
|
||||
public static class EntityDelayedFetchInitializerData extends InitializerData {
|
||||
// per-row state
|
||||
protected @Nullable Object entityIdentifier;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #EntityDelayedFetchInitializer(InitializerParent, NavigablePath, ToOneAttributeMapping, boolean, DomainResultAssembler, BasicResultAssembler)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public EntityDelayedFetchInitializer(
|
||||
FetchParentAccess parentAccess,
|
||||
NavigablePath fetchedNavigable,
|
||||
ToOneAttributeMapping referencedModelPart,
|
||||
boolean selectByUniqueKey,
|
||||
DomainResultAssembler<?> identifierAssembler,
|
||||
BasicResultAssembler<?> discriminatorAssembler) {
|
||||
this(
|
||||
(InitializerParent) parentAccess,
|
||||
fetchedNavigable,
|
||||
referencedModelPart,
|
||||
selectByUniqueKey,
|
||||
identifierAssembler,
|
||||
discriminatorAssembler
|
||||
);
|
||||
public EntityDelayedFetchInitializerData(RowProcessingState rowProcessingState) {
|
||||
super( rowProcessingState );
|
||||
}
|
||||
}
|
||||
|
||||
public EntityDelayedFetchInitializer(
|
||||
InitializerParent parent,
|
||||
InitializerParent<?> parent,
|
||||
NavigablePath fetchedNavigable,
|
||||
ToOneAttributeMapping referencedModelPart,
|
||||
boolean selectByUniqueKey,
|
||||
DomainResultAssembler<?> identifierAssembler,
|
||||
BasicResultAssembler<?> discriminatorAssembler) {
|
||||
DomainResult<?> keyResult,
|
||||
@Nullable BasicFetch<?> discriminatorResult,
|
||||
AssemblerCreationState creationState) {
|
||||
super( creationState );
|
||||
// associations marked with `@NotFound` are ALWAYS eagerly fetched, unless we're resolving the concrete type
|
||||
assert !referencedModelPart.hasNotFoundAction() || referencedModelPart.getEntityMappingType().isConcreteProxy();
|
||||
|
||||
@ -89,8 +81,15 @@ public EntityDelayedFetchInitializer(
|
||||
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 ModelPart getInitializedPart() {
|
||||
}
|
||||
|
||||
@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 void resolveInstance() {
|
||||
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 void resolveInstance() {
|
||||
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 @@ else if ( referencedModelPart.isOptional() && referencedModelPart.isLazy() ) {
|
||||
}
|
||||
|
||||
@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 @@ else if ( !rowProcessingState.isQueryCacheHit() && rowProcessingState.getQueryOp
|
||||
}
|
||||
|
||||
@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 EntityPersister getEntityDescriptor() {
|
||||
}
|
||||
|
||||
@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 boolean isResultInitializer() {
|
||||
}
|
||||
|
||||
@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 String toString() {
|
||||
//#########################
|
||||
// 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 @@ protected DomainResultAssembler<?> getIdentifierAssembler() {
|
||||
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.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 FetchParent getFetchParent() {
|
||||
|
||||
@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 EntityInitializer createInitializer(InitializerParent parent, AssemblerCr
|
||||
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 FetchTiming getTiming() {
|
||||
}
|
||||
|
||||
@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…
x
Reference in New Issue
Block a user