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.Type;
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.asSelfDirtinessTracker;
import static org.hibernate.engine.internal.ManagedTypeHelper.isSelfDirtinessTrackerType;
@ -215,23 +216,7 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter
if ( isTemporarySession ) {
// Add an entry for this entity in the PC of the temp Session
session.getPersistenceContextInternal().addEntity(
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
);
session.getPersistenceContext().addEnhancedProxy( entityKey, asPersistentAttributeInterceptable( target ) );
}
return persister.initializeEnhancedEntityUsedAsProxy(

View File

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

View File

@ -52,6 +52,11 @@ public interface EntityHolder {
*/
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.
*/

View File

@ -114,6 +114,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
private Object version;
private Object entityInstance;
protected Object entityInstanceForNotify;
private EntityHolder holder;
protected State state = State.UNINITIALIZED;
private boolean isOwningInitializer;
private Object[] resolvedEntityState;
@ -444,7 +445,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
// even if the parent instance will not refer to this entity.
final PersistenceContext persistenceContext = rowProcessingState.getSession().getPersistenceContextInternal();
final EntityHolder holder = persistenceContext.claimEntityHolderIfPossible(
holder = persistenceContext.claimEntityHolderIfPossible(
entityKey,
null,
rowProcessingState.getJdbcValuesSourceProcessingState(),
@ -544,9 +545,6 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
registerLoadingEntity( rowProcessingState, entityInstance );
}
}
else if ( !isOwningInitializer ) {
state = State.INITIALIZED;
}
}
else if ( ( entityFromExecutionContext = getEntityFromExecutionContext( rowProcessingState ) ) != null ) {
// 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) {
if ( !isOwningInitializer ) {
return true;
if ( holder.isInitialized() ) {
return rowProcessingState.getJdbcValuesSourceProcessingState().getProcessingOptions()
.getEffectiveOptionalObject() != toInitialize;
}
final EntityEntry entry =
rowProcessingState.getSession().getPersistenceContextInternal().getEntry( toInitialize );
@ -1062,7 +1061,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
else if ( entry.getStatus().isDeletedOrGone() ) {
return true;
}
else {
else if ( isOwningInitializer ) {
if ( isPersistentAttributeInterceptable( toInitialize ) ) {
final PersistentAttributeInterceptor interceptor =
asPersistentAttributeInterceptable( toInitialize ).$$_hibernate_getInterceptor();
@ -1085,6 +1084,9 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
return false;
}
}
else {
return true;
}
}
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 ( entityInstance != null && Hibernate.isInitialized( entityInstance ) ) {
state = State.INITIALIZED;