HHH-17783 Allow early initialization of entity instance by non-owning initializer
This commit is contained in:
parent
710ea629a9
commit
44aec90538
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue