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 08d8f412c0
commit 6162befe00
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.map.MapProxy;
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.AssemblerCreationState;
import org.hibernate.sql.results.graph.DomainResult;
@ -502,7 +503,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
if ( isProxyInstance( proxy ) ) {
if ( entityInstanceFromExecutionContext != null ) {
entityInstance = entityInstanceFromExecutionContext;
registerLoadingEntity( rowProcessingState, entityInstance );
registerLoadingEntityInstanceFromExecutionContext( rowProcessingState, entityInstance );
}
else {
entityInstance = proxy;
@ -519,7 +520,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
}
else if ( entityInstanceFromExecutionContext != null ) {
entityInstance = entityInstanceFromExecutionContext;
registerLoadingEntity( rowProcessingState, entityInstance );
registerLoadingEntityInstanceFromExecutionContext( rowProcessingState, entityInstance );
}
else {
// 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) {
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;
}
@ -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()
.registerLoadingEntity(
entityKey,

View File

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

View File

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