HHH-16744 Wrong class created when reusing a join column for different entities in multiple ManyToOne

This commit is contained in:
Andrea Boriero 2023-06-12 19:12:32 +02:00 committed by Andrea Boriero
parent c5e76ece99
commit 70d8ed2ca2
4 changed files with 48 additions and 38 deletions

View File

@ -35,6 +35,8 @@ public abstract class AbstractBatchEntitySelectFetchInitializer extends Abstract
protected Object entityInstance; protected Object entityInstance;
protected EntityKey entityKey; protected EntityKey entityKey;
protected State state = State.UNINITIALIZED;
public AbstractBatchEntitySelectFetchInitializer( public AbstractBatchEntitySelectFetchInitializer(
FetchParentAccess parentAccess, FetchParentAccess parentAccess,
ToOneAttributeMapping referencedModelPart, ToOneAttributeMapping referencedModelPart,
@ -61,20 +63,6 @@ public abstract class AbstractBatchEntitySelectFetchInitializer extends Abstract
@Override @Override
public void resolveKey(RowProcessingState rowProcessingState) { public void resolveKey(RowProcessingState rowProcessingState) {
final Object entityIdentifier = identifierAssembler.assemble( rowProcessingState );
if ( entityIdentifier == null ) {
return;
}
entityKey = new EntityKey( entityIdentifier, concreteDescriptor );
rowProcessingState.getSession().getPersistenceContext()
.getBatchFetchQueue().addBatchLoadableEntityKey( entityKey );
registerResolutionListener();
}
@Override
public void resolveInstance(RowProcessingState rowProcessingState) {
} }
@Override @Override
@ -83,10 +71,38 @@ public abstract class AbstractBatchEntitySelectFetchInitializer extends Abstract
protected abstract void registerResolutionListener(); protected abstract void registerResolutionListener();
protected void resolveKey(
RowProcessingState rowProcessingState,
ToOneAttributeMapping referencedModelPart,
FetchParentAccess parentAccess) {
if ( state != State.UNINITIALIZED ) {
return;
}
if ( !isAttributeAssignableToConcreteDescriptor( parentAccess, referencedModelPart ) ) {
state = State.MISSING;
return;
}
final Object entityIdentifier = identifierAssembler.assemble( rowProcessingState );
if ( entityIdentifier == null ) {
state = State.MISSING;
}
else {
entityKey = new EntityKey( entityIdentifier, concreteDescriptor );
state = State.KEY_RESOLVED;
rowProcessingState.getSession().getPersistenceContext()
.getBatchFetchQueue().addBatchLoadableEntityKey( entityKey );
registerResolutionListener();
}
}
@Override @Override
public void finishUpRow(RowProcessingState rowProcessingState) { public void finishUpRow(RowProcessingState rowProcessingState) {
entityInstance = null; entityInstance = null;
entityKey = null; entityKey = null;
state = State.UNINITIALIZED;
clearResolutionListeners(); clearResolutionListeners();
} }
@ -154,4 +170,11 @@ public abstract class AbstractBatchEntitySelectFetchInitializer extends Abstract
return concreteDescriptor; return concreteDescriptor;
} }
enum State {
UNINITIALIZED,
MISSING,
KEY_RESOLVED,
INITIALIZED
}
} }

View File

@ -63,6 +63,7 @@ public class BatchEntityInsideEmbeddableSelectFetchInitializer extends AbstractB
@Override @Override
public void resolveInstance(RowProcessingState rowProcessingState) { public void resolveInstance(RowProcessingState rowProcessingState) {
resolveKey( rowProcessingState, referencedModelPart, parentAccess );
if ( entityKey == null ) { if ( entityKey == null ) {
return; return;
} }

View File

@ -23,6 +23,7 @@ import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.FetchParentAccess;
import org.hibernate.sql.results.graph.entity.EntityInitializer; import org.hibernate.sql.results.graph.entity.EntityInitializer;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
public class BatchEntitySelectFetchInitializer extends AbstractBatchEntitySelectFetchInitializer { public class BatchEntitySelectFetchInitializer extends AbstractBatchEntitySelectFetchInitializer {
private Map<EntityKey, List<ParentInfo>> toBatchLoad; private Map<EntityKey, List<ParentInfo>> toBatchLoad;
@ -36,6 +37,11 @@ public class BatchEntitySelectFetchInitializer extends AbstractBatchEntitySelect
super( parentAccess, referencedModelPart, fetchedNavigable, concreteDescriptor, identifierAssembler ); super( parentAccess, referencedModelPart, fetchedNavigable, concreteDescriptor, identifierAssembler );
} }
@Override
public void resolveInstance(RowProcessingState rowProcessingState) {
resolveKey( rowProcessingState, referencedModelPart, parentAccess );
}
@Override @Override
protected void registerResolutionListener() { protected void registerResolutionListener() {
parentAccess.registerResolutionListener( parentInstance -> { parentAccess.registerResolutionListener( parentInstance -> {

View File

@ -28,7 +28,7 @@ import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
public class BatchInitializeEntitySelectFetchInitializer extends AbstractBatchEntitySelectFetchInitializer { public class BatchInitializeEntitySelectFetchInitializer extends AbstractBatchEntitySelectFetchInitializer {
private final Set<EntityKey> toBatchLoad = new HashSet<>(); private final Set<EntityKey> toBatchLoad = new HashSet<>();
private State state = State.UNINITIALIZED;
public BatchInitializeEntitySelectFetchInitializer( public BatchInitializeEntitySelectFetchInitializer(
FetchParentAccess parentAccess, FetchParentAccess parentAccess,
@ -44,18 +44,11 @@ public class BatchInitializeEntitySelectFetchInitializer extends AbstractBatchEn
// No-op, because we resolve a proxy // No-op, because we resolve a proxy
} }
@Override
public void resolveKey(RowProcessingState rowProcessingState) {
if ( state != State.UNINITIALIZED ) {
return;
}
super.resolveKey( rowProcessingState );
state = entityKey == null ? State.MISSING : State.KEY_RESOLVED;
}
@Override @Override
public void resolveInstance(RowProcessingState rowProcessingState) { public void resolveInstance(RowProcessingState rowProcessingState) {
if ( state != State.KEY_RESOLVED ) { resolveKey( rowProcessingState, referencedModelPart, parentAccess );
if ( entityKey == null ) {
return; return;
} }
@ -87,12 +80,6 @@ public class BatchInitializeEntitySelectFetchInitializer extends AbstractBatchEn
return state == State.INITIALIZED; return state == State.INITIALIZED;
} }
@Override
public void finishUpRow(RowProcessingState rowProcessingState) {
super.finishUpRow( rowProcessingState );
state = State.UNINITIALIZED;
}
@Override @Override
public void endLoading(ExecutionContext context) { public void endLoading(ExecutionContext context) {
final SharedSessionContractImplementor session = context.getSession(); final SharedSessionContractImplementor session = context.getSession();
@ -107,11 +94,4 @@ public class BatchInitializeEntitySelectFetchInitializer extends AbstractBatchEn
return "BatchInitializeEntitySelectFetchInitializer(" + LoggingHelper.toLoggableString( getNavigablePath() ) + ")"; return "BatchInitializeEntitySelectFetchInitializer(" + LoggingHelper.toLoggableString( getNavigablePath() ) + ")";
} }
enum State {
UNINITIALIZED,
MISSING,
KEY_RESOLVED,
INITIALIZED
}
} }