HHH-16423 LazyInitializationException when calling em.refresh() on entity with lazy and eager children

This commit is contained in:
Andrea Boriero 2023-04-06 12:52:36 +02:00 committed by Christian Beikov
parent 4c1fe081ba
commit 8480eca26f
3 changed files with 25 additions and 13 deletions

View File

@ -45,6 +45,7 @@ import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
import org.hibernate.proxy.LazyInitializer; import org.hibernate.proxy.LazyInitializer;
import org.hibernate.proxy.map.MapProxy; import org.hibernate.proxy.map.MapProxy;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.results.graph.AbstractFetchParentAccess; import org.hibernate.sql.results.graph.AbstractFetchParentAccess;
import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.AssemblerCreationState;
import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResult;
@ -502,7 +503,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
if ( isProxyInstance( proxy ) ) { if ( isProxyInstance( proxy ) ) {
if ( entityInstanceFromExecutionContext != null ) { if ( entityInstanceFromExecutionContext != null ) {
entityInstance = entityInstanceFromExecutionContext; entityInstance = entityInstanceFromExecutionContext;
registerLoadingEntity( rowProcessingState, entityInstance ); registerLoadingEntityInstanceFromExecutionContext( rowProcessingState, entityInstance );
} }
else { else {
entityInstance = proxy; entityInstance = proxy;
@ -519,7 +520,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
} }
else if ( entityInstanceFromExecutionContext != null ) { else if ( entityInstanceFromExecutionContext != null ) {
entityInstance = entityInstanceFromExecutionContext; entityInstance = entityInstanceFromExecutionContext;
registerLoadingEntity( rowProcessingState, entityInstance ); registerLoadingEntityInstanceFromExecutionContext( rowProcessingState, entityInstance );
} }
else { else {
// look to see if another initializer from a parent load context or an earlier // look to see if another initializer from a parent load context or an earlier
@ -538,7 +539,19 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
} }
} }
protected abstract void registerLoadingEntityInstanceFromExecutionContext(
RowProcessingState rowProcessingState,
Object instance);
protected Object getEntityInstanceFromExecutionContext(RowProcessingState rowProcessingState) { protected Object getEntityInstanceFromExecutionContext(RowProcessingState rowProcessingState) {
final ExecutionContext executionContext = rowProcessingState.getJdbcValuesSourceProcessingState()
.getExecutionContext();
final Object entityInstanceFromExecutionContext = executionContext.getEntityInstance();
if ( entityInstanceFromExecutionContext != null
&& getConcreteDescriptor().getJavaType().isInstance( entityInstanceFromExecutionContext )
&& getEntityKey().getIdentifier().equals( executionContext.getEntityId() ) ) {
return entityInstanceFromExecutionContext;
}
return null; return null;
} }
@ -702,7 +715,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
); );
} }
private void registerLoadingEntity(RowProcessingState rowProcessingState, Object instance) { protected void registerLoadingEntity(RowProcessingState rowProcessingState, Object instance) {
rowProcessingState.getJdbcValuesSourceProcessingState() rowProcessingState.getJdbcValuesSourceProcessingState()
.registerLoadingEntity( .registerLoadingEntity(
entityKey, entityKey,

View File

@ -117,6 +117,11 @@ public class EntityJoinedFetchInitializer extends AbstractEntityInitializer {
return super.getProxy( persistenceContext ); return super.getProxy( persistenceContext );
} }
@Override
protected void registerLoadingEntityInstanceFromExecutionContext(RowProcessingState rowProcessingState, Object instance) {
// we want the EntityResultInitializer to take care of the instance
}
@Override @Override
protected String getSimpleConcreteImplName() { protected String getSimpleConcreteImplName() {
return CONCRETE_NAME; return CONCRETE_NAME;

View File

@ -8,7 +8,6 @@ package org.hibernate.sql.results.graph.entity.internal;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.spi.NavigablePath; 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.AssemblerCreationState;
import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.Fetch; import org.hibernate.sql.results.graph.Fetch;
@ -60,15 +59,10 @@ public class EntityResultInitializer extends AbstractEntityInitializer {
} }
@Override @Override
protected Object getEntityInstanceFromExecutionContext(RowProcessingState rowProcessingState) { protected void registerLoadingEntityInstanceFromExecutionContext(
final ExecutionContext executionContext = rowProcessingState.getJdbcValuesSourceProcessingState() RowProcessingState rowProcessingState,
.getExecutionContext(); Object instance) {
final Object entityInstanceFromExecutionContext = executionContext.getEntityInstance(); registerLoadingEntity( rowProcessingState, instance );
if ( entityInstanceFromExecutionContext != null
&& getEntityKey().getIdentifier().equals( executionContext.getEntityId() ) ) {
return entityInstanceFromExecutionContext;
}
return null;
} }
} }