HHH-17783 Allow early initialization of entity instance by non-owning initializer

This commit is contained in:
Marco Belladelli 2024-02-28 12:08:23 +01:00 committed by Steve Ebersole
parent 710ea629a9
commit 44aec90538
5 changed files with 23 additions and 25 deletions

View File

@ -22,6 +22,7 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.asSelfDirtinessTracker; import static org.hibernate.engine.internal.ManagedTypeHelper.asSelfDirtinessTracker;
import static org.hibernate.engine.internal.ManagedTypeHelper.isSelfDirtinessTrackerType; import static org.hibernate.engine.internal.ManagedTypeHelper.isSelfDirtinessTrackerType;
@ -215,23 +216,7 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter
if ( isTemporarySession ) { if ( isTemporarySession ) {
// Add an entry for this entity in the PC of the temp Session // Add an entry for this entity in the PC of the temp Session
session.getPersistenceContextInternal().addEntity( session.getPersistenceContext().addEnhancedProxy( entityKey, asPersistentAttributeInterceptable( target ) );
target,
org.hibernate.engine.spi.Status.READ_ONLY,
// loaded state
ArrayHelper.filledArray(
LazyPropertyInitializer.UNFETCHED_PROPERTY,
Object.class,
persister.getPropertyTypes().length
),
entityKey,
persister.getVersion( target ),
LockMode.NONE,
// we assume an entry exists in the db
true,
persister,
true
);
} }
return persister.initializeEnhancedEntityUsedAsProxy( return persister.initializeEnhancedEntityUsedAsProxy(

View File

@ -516,6 +516,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
final Object entity = holder.entity; final Object entity = holder.entity;
if ( holder.proxy != null ) { if ( holder.proxy != null ) {
holder.entity = null; holder.entity = null;
holder.state = EntityHolderState.UNINITIALIZED;
entitiesByKey.put( key, holder ); entitiesByKey.put( key, holder );
} }
return entity; return entity;
@ -2199,6 +2200,11 @@ public class StatefulPersistenceContext implements PersistenceContext {
processingState.registerReloadedEntityHolder( this ); processingState.registerReloadedEntityHolder( this );
} }
@Override
public boolean isInitialized() {
return state == EntityHolderState.INITIALIZED;
}
@Override @Override
public boolean isEventuallyInitialized() { public boolean isEventuallyInitialized() {
return state == EntityHolderState.INITIALIZED || entityInitializer != null; return state == EntityHolderState.INITIALIZED || entityInitializer != null;

View File

@ -52,6 +52,11 @@ public interface EntityHolder {
*/ */
void markAsReloaded(JdbcValuesSourceProcessingState processingState); void markAsReloaded(JdbcValuesSourceProcessingState processingState);
/**
* Whether the entity is already initialized
*/
boolean isInitialized();
/** /**
* Whether the entity is already initialized or will be initialized through an initializer eventually. * Whether the entity is already initialized or will be initialized through an initializer eventually.
*/ */

View File

@ -114,6 +114,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
private Object version; private Object version;
private Object entityInstance; private Object entityInstance;
protected Object entityInstanceForNotify; protected Object entityInstanceForNotify;
private EntityHolder holder;
protected State state = State.UNINITIALIZED; protected State state = State.UNINITIALIZED;
private boolean isOwningInitializer; private boolean isOwningInitializer;
private Object[] resolvedEntityState; private Object[] resolvedEntityState;
@ -444,7 +445,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
// even if the parent instance will not refer to this entity. // even if the parent instance will not refer to this entity.
final PersistenceContext persistenceContext = rowProcessingState.getSession().getPersistenceContextInternal(); final PersistenceContext persistenceContext = rowProcessingState.getSession().getPersistenceContextInternal();
final EntityHolder holder = persistenceContext.claimEntityHolderIfPossible( holder = persistenceContext.claimEntityHolderIfPossible(
entityKey, entityKey,
null, null,
rowProcessingState.getJdbcValuesSourceProcessingState(), rowProcessingState.getJdbcValuesSourceProcessingState(),
@ -544,9 +545,6 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
registerLoadingEntity( rowProcessingState, entityInstance ); registerLoadingEntity( rowProcessingState, entityInstance );
} }
} }
else if ( !isOwningInitializer ) {
state = State.INITIALIZED;
}
} }
else if ( ( entityFromExecutionContext = getEntityFromExecutionContext( rowProcessingState ) ) != null ) { else if ( ( entityFromExecutionContext = getEntityFromExecutionContext( rowProcessingState ) ) != null ) {
// This is the entity to refresh, so don't set the state to initialized // This is the entity to refresh, so don't set the state to initialized
@ -1050,8 +1048,9 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
} }
protected boolean skipInitialization(Object toInitialize, RowProcessingState rowProcessingState) { protected boolean skipInitialization(Object toInitialize, RowProcessingState rowProcessingState) {
if ( !isOwningInitializer ) { if ( holder.isInitialized() ) {
return true; return rowProcessingState.getJdbcValuesSourceProcessingState().getProcessingOptions()
.getEffectiveOptionalObject() != toInitialize;
} }
final EntityEntry entry = final EntityEntry entry =
rowProcessingState.getSession().getPersistenceContextInternal().getEntry( toInitialize ); rowProcessingState.getSession().getPersistenceContextInternal().getEntry( toInitialize );
@ -1062,7 +1061,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
else if ( entry.getStatus().isDeletedOrGone() ) { else if ( entry.getStatus().isDeletedOrGone() ) {
return true; return true;
} }
else { else if ( isOwningInitializer ) {
if ( isPersistentAttributeInterceptable( toInitialize ) ) { if ( isPersistentAttributeInterceptable( toInitialize ) ) {
final PersistentAttributeInterceptor interceptor = final PersistentAttributeInterceptor interceptor =
asPersistentAttributeInterceptable( toInitialize ).$$_hibernate_getInterceptor(); asPersistentAttributeInterceptable( toInitialize ).$$_hibernate_getInterceptor();
@ -1085,6 +1084,9 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
return false; return false;
} }
} }
else {
return true;
}
} }
private boolean isReadOnly(RowProcessingState rowProcessingState, SharedSessionContractImplementor persistenceContext) { private boolean isReadOnly(RowProcessingState rowProcessingState, SharedSessionContractImplementor persistenceContext) {

View File

@ -154,7 +154,7 @@ public class EntitySelectFetchInitializer implements EntityInitializer {
) )
); );
} }
entityInstance = holder.getEntity(); entityInstance = persistenceContext.proxyFor( holder, concreteDescriptor );
if ( holder.getEntityInitializer() == null ) { if ( holder.getEntityInitializer() == null ) {
if ( entityInstance != null && Hibernate.isInitialized( entityInstance ) ) { if ( entityInstance != null && Hibernate.isInitialized( entityInstance ) ) {
state = State.INITIALIZED; state = State.INITIALIZED;