HHH-14730 Avoid loading the same entity proxy twice for the same result set
This commit is contained in:
parent
98e64579fa
commit
6c98441518
|
@ -667,17 +667,10 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
PersistenceContext persistenceContext) {
|
||||
final EntityEntry entry = persistenceContext.getEntry( toInitialize );
|
||||
if ( entry != null ) {
|
||||
if ( entry.getStatus() != Status.LOADING ) {
|
||||
final Object optionalEntityInstance = rowProcessingState.getJdbcValuesSourceProcessingState()
|
||||
.getProcessingOptions()
|
||||
.getEffectiveOptionalObject();
|
||||
// If the instance to initialize is the main entity, we can't skip this
|
||||
// This can happen if we initialize an enhanced proxy
|
||||
if ( !isEntityReturn() || toInitialize != optionalEntityInstance ) {
|
||||
if ( skipInitialization( toInitialize, rowProcessingState, entry ) ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Object entity = persistenceContext.getEntity( entityKey );
|
||||
assert entity == null || entity == toInitialize;
|
||||
|
@ -863,6 +856,25 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
}
|
||||
}
|
||||
|
||||
protected boolean skipInitialization(
|
||||
Object toInitialize,
|
||||
RowProcessingState rowProcessingState,
|
||||
EntityEntry entry) {
|
||||
// If the instance to initialize is the main entity, we can't skip this
|
||||
// This can happen if we initialize an enhanced proxy
|
||||
if ( entry.getStatus() != Status.LOADING ) {
|
||||
final Object optionalEntityInstance = rowProcessingState.getJdbcValuesSourceProcessingState()
|
||||
.getProcessingOptions()
|
||||
.getEffectiveOptionalObject();
|
||||
// If the instance to initialize is the main entity, we can't skip this
|
||||
// This can happen if we initialize an enhanced proxy
|
||||
if ( !isEntityReturn() || toInitialize != optionalEntityInstance ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isReadOnly(
|
||||
RowProcessingState rowProcessingState,
|
||||
SharedSessionContractImplementor persistenceContext) {
|
||||
|
|
|
@ -7,7 +7,12 @@
|
|||
package org.hibernate.sql.results.graph.entity.internal;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
|
||||
import org.hibernate.engine.spi.EntityEntry;
|
||||
import org.hibernate.engine.spi.PersistenceContext;
|
||||
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
|
||||
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
|
||||
import org.hibernate.engine.spi.Status;
|
||||
import org.hibernate.internal.log.LoggingHelper;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
||||
|
@ -16,6 +21,7 @@ import org.hibernate.sql.results.graph.AssemblerCreationState;
|
|||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.entity.AbstractEntityInitializer;
|
||||
import org.hibernate.sql.results.graph.entity.EntityResultGraphNode;
|
||||
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
|
||||
|
||||
/**
|
||||
* @author Andrea Boriero
|
||||
|
@ -80,4 +86,21 @@ public class EntityJoinedFetchInitializer extends AbstractEntityInitializer {
|
|||
public String toString() {
|
||||
return "EntityJoinedFetchInitializer(" + LoggingHelper.toLoggableString( getNavigablePath() ) + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean skipInitialization(
|
||||
Object toInitialize, RowProcessingState rowProcessingState, EntityEntry entry) {
|
||||
if ( toInitialize instanceof PersistentAttributeInterceptable ) {
|
||||
final PersistentAttributeInterceptor interceptor = ( (PersistentAttributeInterceptable) toInitialize ).$$_hibernate_getInterceptor();
|
||||
if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor ) {
|
||||
if ( entry.getStatus() != Status.LOADING ) {
|
||||
// Avoid loading the same entity proxy twice for the same result set: it could lead to errors,
|
||||
// because some code writes to its input (ID in hydrated state replaced by the loaded entity, in particular).
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.skipInitialization( toInitialize, rowProcessingState, entry );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
|
|
Loading…
Reference in New Issue