Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -131,100 +131,88 @@ protected void resolveInstanceFromIdentifier(Data data) {

@Override
public void resolveInstance(Object instance, Data data) {
if ( instance == null ) {
final boolean identifierResolved = resolveIdentifier( instance, data );
if ( data.entityIdentifier == null ) {
data.setState( State.MISSING );
data.entityKey = null;
data.setInstance( null );
return;
}
final var rowProcessingState = data.getRowProcessingState();
final var session = rowProcessingState.getSession();
final var persistenceContext = session.getPersistenceContextInternal();
// Only need to extract the identifier if the identifier has a many to one
final LazyInitializer lazyInitializer = extractLazyInitializer( instance );
data.entityIdentifier = null;
if ( lazyInitializer == null ) {
// Entity is most probably initialized
data.setInstance( instance );
final PersistentAttributeInterceptor interceptor;
if ( concreteDescriptor.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading()
&& isPersistentAttributeInterceptable( instance )
&& ( interceptor = getAttributeInterceptor( instance ) ) instanceof EnhancementAsProxyLazinessInterceptor ) {
final EnhancementAsProxyLazinessInterceptor enhancementInterceptor = (EnhancementAsProxyLazinessInterceptor) interceptor;
if ( enhancementInterceptor.isInitialized() ) {
data.setState( State.INITIALIZED );
else {
final var rowProcessingState = data.getRowProcessingState();
final var session = rowProcessingState.getSession();
final var persistenceContext = session.getPersistenceContextInternal();
final LazyInitializer lazyInitializer = extractLazyInitializer( instance );
if ( lazyInitializer == null ) {
// Entity is most probably initialized
final PersistentAttributeInterceptor interceptor;
if ( concreteDescriptor.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading()
&& isPersistentAttributeInterceptable( instance )
&& ( interceptor = getAttributeInterceptor( instance ) ) instanceof EnhancementAsProxyLazinessInterceptor ) {
final EnhancementAsProxyLazinessInterceptor enhancementInterceptor = (EnhancementAsProxyLazinessInterceptor) interceptor;
if ( enhancementInterceptor.isInitialized() ) {
data.setState( State.INITIALIZED );
}
else {
data.setState( State.RESOLVED );
}
}
else {
// If the entity initializer is null, we know the entity is fully initialized,
// otherwise it will be initialized by some other initializer
data.setState( State.RESOLVED );
data.entityIdentifier = enhancementInterceptor.getIdentifier();
}
}
else {
// If the entity initializer is null, we know the entity is fully initialized,
// otherwise it will be initialized by some other initializer
else if ( lazyInitializer.isUninitialized() ) {
data.setState( State.RESOLVED );
data.entityIdentifier = concreteDescriptor.getIdentifier( instance, session );
}
if ( data.entityIdentifier == null ) {
data.entityIdentifier = concreteDescriptor.getIdentifier( instance, session );
else {
// Entity is initialized
data.setState( State.INITIALIZED );
}
}
else if ( lazyInitializer.isUninitialized() ) {
data.setState( State.RESOLVED );
data.entityIdentifier = lazyInitializer.getInternalIdentifier();
}
else {
// Entity is initialized
data.setState( State.INITIALIZED );
data.entityIdentifier = lazyInitializer.getInternalIdentifier();
data.setInstance( lazyInitializer.getImplementation() );
}

data.entityKey = new EntityKey( data.entityIdentifier, concreteDescriptor );
final var entityHolder = persistenceContext.getEntityHolder(
data.entityKey
);
data.entityKey = new EntityKey( data.entityIdentifier, concreteDescriptor );
final var entityHolder = persistenceContext.getEntityHolder( data.entityKey );

if ( entityHolder == null || entityHolder.getEntity() != instance && entityHolder.getProxy() != instance ) {
// the existing entity instance is detached or transient
if ( entityHolder != null ) {
final var managed = entityHolder.getManagedObject();
data.setInstance( managed );
data.entityKey = entityHolder.getEntityKey();
data.entityIdentifier = data.entityKey.getIdentifier();
if ( entityHolder.isInitialized() ) {
data.setState( State.INITIALIZED );
if ( entityHolder == null || instance == null
|| entityHolder.getEntity() != instance && entityHolder.getProxy() != instance ) {
// the existing entity instance is detached or transient
if ( entityHolder != null ) {
final var managed = entityHolder.getManagedObject();
data.setInstance( managed );
data.entityKey = entityHolder.getEntityKey();
data.entityIdentifier = data.entityKey.getIdentifier();
data.setState( entityHolder.isInitialized() ? State.INITIALIZED : State.RESOLVED );
}
else {
data.setState( State.RESOLVED );
}
}
else {
data.setState( State.RESOLVED );
data.setInstance( instance );
}
}

if ( data.getState() == State.RESOLVED ) {
// similar to resolveInstanceFromIdentifier, but we already have the holder here
if ( data.batchDisabled ) {
initialize( data, entityHolder, session, persistenceContext );
}
else if ( entityHolder == null || !entityHolder.isEventuallyInitialized() ) {
// 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
registerResolutionListener( data );
registerToBatchFetchQueue( data );
if ( data.getState() == State.RESOLVED ) {
// similar to resolveInstanceFromIdentifier, but we already have the holder here
if ( data.batchDisabled ) {
initialize( data, entityHolder, session, persistenceContext );
}
else if ( entityHolder == null || !entityHolder.isEventuallyInitialized() ) {
// 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
registerResolutionListener( data );
registerToBatchFetchQueue( data );
}
}
}

if ( keyIsEager ) {
final Initializer<?> initializer = keyAssembler.getInitializer();
assert initializer != null;
initializer.resolveInstance( data.entityIdentifier, rowProcessingState );
}
else if ( rowProcessingState.needsResolveState() ) {
// Resolve the state of the identifier if result caching is enabled and this is not a query cache hit
keyAssembler.resolveState( rowProcessingState );
if ( keyIsEager && !identifierResolved ) {
final Initializer<?> initializer = keyAssembler.getInitializer();
assert initializer != null;
initializer.resolveInstance( data.entityIdentifier, rowProcessingState );
}
else if ( rowProcessingState.needsResolveState() && !identifierResolved ) {
// Resolve the state of the identifier if result caching is enabled and this is not a query cache hit
keyAssembler.resolveState( rowProcessingState );
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.log.LoggingHelper;
import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.DiscriminatedAssociationModelPart;
import org.hibernate.metamodel.mapping.DiscriminatorMapping;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.proxy.LazyInitializer;
Expand Down Expand Up @@ -53,6 +55,7 @@ public class DiscriminatedEntityInitializer
private final boolean resultInitializer;
private final boolean keyIsEager;
private final boolean hasLazySubInitializer;
protected final boolean isReadOnly;

public static class DiscriminatedEntityInitializerData extends InitializerData {
protected EntityPersister concreteDescriptor;
Expand Down Expand Up @@ -90,6 +93,16 @@ public DiscriminatedEntityInitializer(
this.keyIsEager = initializer.isEager();
this.hasLazySubInitializer = !initializer.isEager() || initializer.hasLazySubInitializers();
}
this.isReadOnly = isReadOnly( fetchedPart );
}

private static boolean isReadOnly(DiscriminatedAssociationModelPart fetchedPart) {
final BasicValuedModelPart keyPart = fetchedPart.getKeyPart();
final DiscriminatorMapping discriminatorMapping = fetchedPart.getDiscriminatorMapping();
return !keyPart.isInsertable()
&& !keyPart.isUpdateable()
&& !discriminatorMapping.isInsertable()
&& !discriminatorMapping.isUpdateable();
}

@Override
Expand Down Expand Up @@ -201,13 +214,16 @@ else if ( instance == null ) {
) );
}

@Override
public void resolveInstance(Object instance, DiscriminatedEntityInitializerData data) {
if ( instance == null ) {
data.setState( State.MISSING );
protected boolean resolveIdentifier(Object instance, DiscriminatedEntityInitializerData data) {
final boolean identifierResolved;
if ( instance == null && !isReadOnly ) {
data.entityIdentifier = null;
data.concreteDescriptor = null;
data.setInstance( null );
identifierResolved = true;
}
else if ( isReadOnly ) {
// When the mapping is read-only, we can't trust the state of the persistence context
resolveKey( data );
identifierResolved = true;
}
else {
final var rowProcessingState = data.getRowProcessingState();
Expand All @@ -217,27 +233,43 @@ public void resolveInstance(Object instance, DiscriminatedEntityInitializerData
data.setState( State.INITIALIZED );
data.concreteDescriptor = session.getEntityPersister( null, instance );
data.entityIdentifier = data.concreteDescriptor.getIdentifier( instance, session );
identifierResolved = false;
}
else if ( lazyInitializer.isUninitialized() ) {
data.setState( eager ? State.RESOLVED : State.INITIALIZED );
// Read the discriminator from the result set if necessary
final Object discriminatorValue = discriminatorValueAssembler.assemble( rowProcessingState );
data.concreteDescriptor = fetchedPart.resolveDiscriminatorValue( discriminatorValue ).getEntityPersister();
data.entityIdentifier = lazyInitializer.getInternalIdentifier();
identifierResolved = true;
}
else {
data.setState( State.INITIALIZED );
data.concreteDescriptor = session.getEntityPersister( null, lazyInitializer.getImplementation() );
data.entityIdentifier = lazyInitializer.getInternalIdentifier();
identifierResolved = false;
}
assert data.entityIdentifier != null;
}
return identifierResolved;
}


@Override
public void resolveInstance(Object instance, DiscriminatedEntityInitializerData data) {
final boolean identifierResolved = resolveIdentifier( instance, data );
if ( data.entityIdentifier == null ) {
data.setState( State.MISSING );
data.concreteDescriptor = null;
data.setInstance( null );
}
else {
final var rowProcessingState = data.getRowProcessingState();
final var session = rowProcessingState.getSession();
final var entityKey = new EntityKey( data.entityIdentifier, data.concreteDescriptor );
final var entityHolder = session.getPersistenceContextInternal().getEntityHolder(
entityKey
);
final var entityHolder = session.getPersistenceContextInternal().getEntityHolder( entityKey );

if ( entityHolder == null || entityHolder.getEntity() != instance && entityHolder.getProxy() != instance ) {
if ( entityHolder == null || instance == null
|| entityHolder.getEntity() != instance && entityHolder.getProxy() != instance ) {
// the existing entity instance is detached or transient
if ( entityHolder != null ) {
final var managed = entityHolder.getManagedObject();
Expand All @@ -254,15 +286,18 @@ else if ( lazyInitializer.isUninitialized() ) {
data.setInstance( instance );
}

if ( keyIsEager ) {
if ( keyIsEager && !identifierResolved ) {
final Initializer<?> initializer = keyValueAssembler.getInitializer();
assert initializer != null;
initializer.resolveInstance( data.entityIdentifier, rowProcessingState );
if ( rowProcessingState.needsResolveState() ) {
discriminatorValueAssembler.resolveState( rowProcessingState );
}
}
else if ( rowProcessingState.needsResolveState() ) {
else if ( rowProcessingState.needsResolveState() && !identifierResolved ) {
// 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 );
discriminatorValueAssembler.resolveState( rowProcessingState );
}
}
}
Expand Down
Loading
Loading