HHH-15694 HibernateException: Unable to resolve property xyz on ManyToOne with BatchSize
This commit is contained in:
parent
47933b36bd
commit
d25c1a44f0
|
@ -27,8 +27,9 @@ public abstract class AbstractBatchEntitySelectFetchInitializer extends Abstract
|
|||
private final NavigablePath navigablePath;
|
||||
|
||||
protected final EntityPersister concreteDescriptor;
|
||||
protected final DomainResultAssembler identifierAssembler;
|
||||
protected final DomainResultAssembler<?> identifierAssembler;
|
||||
protected final ToOneAttributeMapping referencedModelPart;
|
||||
protected final EntityInitializer firstEntityInitializer;
|
||||
|
||||
protected Object entityInstance;
|
||||
protected EntityKey entityKey;
|
||||
|
@ -38,12 +39,13 @@ public abstract class AbstractBatchEntitySelectFetchInitializer extends Abstract
|
|||
ToOneAttributeMapping referencedModelPart,
|
||||
NavigablePath fetchedNavigable,
|
||||
EntityPersister concreteDescriptor,
|
||||
DomainResultAssembler identifierAssembler) {
|
||||
DomainResultAssembler<?> identifierAssembler) {
|
||||
this.parentAccess = parentAccess;
|
||||
this.referencedModelPart = referencedModelPart;
|
||||
this.navigablePath = fetchedNavigable;
|
||||
this.concreteDescriptor = concreteDescriptor;
|
||||
this.identifierAssembler = identifierAssembler;
|
||||
this.firstEntityInitializer = parentAccess.findFirstEntityInitializer();
|
||||
}
|
||||
|
||||
public ModelPart getInitializedPart() {
|
||||
|
@ -62,9 +64,11 @@ public abstract class AbstractBatchEntitySelectFetchInitializer extends Abstract
|
|||
return;
|
||||
}
|
||||
entityKey = new EntityKey( entityIdentifier, concreteDescriptor );
|
||||
addParentInfo();
|
||||
|
||||
rowProcessingState.getSession().getPersistenceContext()
|
||||
.getBatchFetchQueue().addBatchLoadableEntityKey( entityKey );
|
||||
|
||||
registerResolutionListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -75,7 +79,7 @@ public abstract class AbstractBatchEntitySelectFetchInitializer extends Abstract
|
|||
public void initializeInstance(RowProcessingState rowProcessingState) {
|
||||
}
|
||||
|
||||
protected abstract void addParentInfo();
|
||||
protected abstract void registerResolutionListener();
|
||||
|
||||
@Override
|
||||
public void finishUpRow(RowProcessingState rowProcessingState) {
|
||||
|
@ -125,8 +129,8 @@ public abstract class AbstractBatchEntitySelectFetchInitializer extends Abstract
|
|||
);
|
||||
}
|
||||
|
||||
protected static int getPropertyIndex(FetchParentAccess parentAccess, String propertyName) {
|
||||
return parentAccess.findFirstEntityInitializer().getEntityDescriptor().getPropertyIndex( propertyName );
|
||||
protected static int getPropertyIndex(EntityInitializer entityInitializer, String propertyName) {
|
||||
return entityInitializer.getConcreteDescriptor().getPropertyIndex( propertyName );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -27,10 +27,8 @@ import org.hibernate.sql.results.graph.entity.EntityInitializer;
|
|||
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
|
||||
|
||||
public class BatchEntityInsideEmbeddableSelectFetchInitializer extends AbstractBatchEntitySelectFetchInitializer {
|
||||
/*
|
||||
Object[0] will contain the parent EntityKey and Object[1] the parent embeddable instance,
|
||||
*/
|
||||
private final Map<EntityKey, List<Object[]>> toBatchLoad = new HashMap<>();
|
||||
private final Map<EntityKey, List<ParentInfo>> toBatchLoad = new HashMap<>();
|
||||
private final String rootEmbeddablePropertyName;
|
||||
|
||||
/**
|
||||
* Marker value for batch properties, needed by the EmbeddableInitializer to instantiate the
|
||||
|
@ -52,8 +50,14 @@ public class BatchEntityInsideEmbeddableSelectFetchInitializer extends AbstractB
|
|||
ToOneAttributeMapping referencedModelPart,
|
||||
NavigablePath fetchedNavigable,
|
||||
EntityPersister concreteDescriptor,
|
||||
DomainResultAssembler identifierAssembler) {
|
||||
DomainResultAssembler<?> identifierAssembler) {
|
||||
super( parentAccess, referencedModelPart, fetchedNavigable, concreteDescriptor, identifierAssembler );
|
||||
|
||||
rootEmbeddablePropertyName = getRootEmbeddablePropertyName(
|
||||
firstEntityInitializer,
|
||||
parentAccess,
|
||||
referencedModelPart
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -66,21 +70,23 @@ public class BatchEntityInsideEmbeddableSelectFetchInitializer extends AbstractB
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void addParentInfo() {
|
||||
final List<Object[]> parents = getBatchInfos();
|
||||
protected void registerResolutionListener() {
|
||||
final List<ParentInfo> batchParentInfos = getBatchInfos();
|
||||
|
||||
parentAccess.registerResolutionListener(
|
||||
o ->
|
||||
parents.add(
|
||||
new Object[] {
|
||||
parentAccess.findFirstEntityInitializer().getEntityKey(),
|
||||
o
|
||||
}
|
||||
batchParentInfos.add(
|
||||
new ParentInfo(
|
||||
firstEntityInitializer.getEntityKey(),
|
||||
o,
|
||||
getPropertyIndex( firstEntityInitializer, rootEmbeddablePropertyName )
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private List<Object[]> getBatchInfos() {
|
||||
List<Object[]> objects = toBatchLoad.get( entityKey );
|
||||
private List<ParentInfo> getBatchInfos() {
|
||||
List<ParentInfo> objects = toBatchLoad.get( entityKey );
|
||||
if ( objects == null ) {
|
||||
objects = new ArrayList<>();
|
||||
toBatchLoad.put( entityKey, objects );
|
||||
|
@ -88,26 +94,35 @@ public class BatchEntityInsideEmbeddableSelectFetchInitializer extends AbstractB
|
|||
return objects;
|
||||
}
|
||||
|
||||
private static class ParentInfo {
|
||||
private final EntityKey initializerEntityKey;
|
||||
private final Object parentInstance;
|
||||
private final int propertyIndex;
|
||||
|
||||
public ParentInfo(EntityKey initializerEntityKey, Object parentInstance, int propertyIndex) {
|
||||
this.initializerEntityKey = initializerEntityKey;
|
||||
this.parentInstance = parentInstance;
|
||||
this.propertyIndex = propertyIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endLoading(ExecutionContext context) {
|
||||
final EntityInitializer entityInitializer = parentAccess.findFirstEntityInitializer();
|
||||
final String rootEmbeddablePropertyName = getRootEmbeddablePropertyName();
|
||||
final int rootEmbeddablePropertyIndex = getPropertyIndex( parentAccess, rootEmbeddablePropertyName );
|
||||
toBatchLoad.forEach(
|
||||
(entityKey, parentInfos) -> {
|
||||
final SharedSessionContractImplementor session = context.getSession();
|
||||
final Object loadedInstance = loadInstance( entityKey, referencedModelPart, session );
|
||||
for ( Object[] parentInfo : parentInfos ) {
|
||||
for ( ParentInfo parentInfo : parentInfos ) {
|
||||
final PersistenceContext persistenceContext = session.getPersistenceContext();
|
||||
setInstance(
|
||||
entityInitializer,
|
||||
firstEntityInitializer,
|
||||
referencedModelPart,
|
||||
rootEmbeddablePropertyName,
|
||||
rootEmbeddablePropertyIndex,
|
||||
parentInfo.propertyIndex,
|
||||
loadedInstance,
|
||||
parentInfo[1],
|
||||
(EntityKey) parentInfo[0],
|
||||
persistenceContext.getEntry( persistenceContext.getEntity( (EntityKey) parentInfo[0] ) ),
|
||||
parentInfo.parentInstance,
|
||||
parentInfo.initializerEntityKey,
|
||||
persistenceContext.getEntry( persistenceContext.getEntity( parentInfo.initializerEntityKey ) ),
|
||||
session
|
||||
);
|
||||
}
|
||||
|
@ -164,8 +179,11 @@ public class BatchEntityInsideEmbeddableSelectFetchInitializer extends AbstractB
|
|||
}
|
||||
}
|
||||
|
||||
protected String getRootEmbeddablePropertyName() {
|
||||
final NavigablePath entityPath = parentAccess.findFirstEntityDescriptorAccess().getNavigablePath();
|
||||
protected static String getRootEmbeddablePropertyName(
|
||||
EntityInitializer firstEntityInitializer,
|
||||
FetchParentAccess parentAccess,
|
||||
ToOneAttributeMapping referencedModelPart) {
|
||||
final NavigablePath entityPath = firstEntityInitializer.getNavigablePath();
|
||||
NavigablePath navigablePath = parentAccess.getNavigablePath();
|
||||
if ( navigablePath == entityPath ) {
|
||||
return referencedModelPart.getPartName();
|
||||
|
|
|
@ -24,27 +24,33 @@ import org.hibernate.sql.results.graph.FetchParentAccess;
|
|||
import org.hibernate.sql.results.graph.entity.EntityInitializer;
|
||||
|
||||
public class BatchEntitySelectFetchInitializer extends AbstractBatchEntitySelectFetchInitializer {
|
||||
private final Map<EntityKey, List<Object>> toBatchLoad = new HashMap<>();
|
||||
private final Map<EntityKey, List<ParentInfo>> toBatchLoad = new HashMap<>();
|
||||
|
||||
public BatchEntitySelectFetchInitializer(
|
||||
FetchParentAccess parentAccess,
|
||||
ToOneAttributeMapping referencedModelPart,
|
||||
NavigablePath fetchedNavigable,
|
||||
EntityPersister concreteDescriptor,
|
||||
DomainResultAssembler identifierAssembler) {
|
||||
DomainResultAssembler<?> identifierAssembler) {
|
||||
super( parentAccess, referencedModelPart, fetchedNavigable, concreteDescriptor, identifierAssembler );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addParentInfo() {
|
||||
final List<Object> parents = getBatchInfos();
|
||||
protected void registerResolutionListener() {
|
||||
final List<ParentInfo> parents = getParentInfos();
|
||||
parentAccess.registerResolutionListener(
|
||||
o -> parents.add( o )
|
||||
o ->
|
||||
parents.add(
|
||||
new ParentInfo(
|
||||
o,
|
||||
getPropertyIndex( firstEntityInitializer, referencedModelPart.getPartName() )
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private List<Object> getBatchInfos() {
|
||||
List<Object> objects = toBatchLoad.get( entityKey );
|
||||
private List<ParentInfo> getParentInfos() {
|
||||
List<ParentInfo> objects = toBatchLoad.get( entityKey );
|
||||
if ( objects == null ) {
|
||||
objects = new ArrayList<>();
|
||||
toBatchLoad.put( entityKey, objects );
|
||||
|
@ -52,21 +58,29 @@ public class BatchEntitySelectFetchInitializer extends AbstractBatchEntitySelect
|
|||
return objects;
|
||||
}
|
||||
|
||||
private static class ParentInfo {
|
||||
private final Object parentInstance;
|
||||
private final int propertyIndex;
|
||||
|
||||
public ParentInfo(Object parentInstance, int propertyIndex) {
|
||||
this.parentInstance = parentInstance;
|
||||
this.propertyIndex = propertyIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endLoading(ExecutionContext context) {
|
||||
final EntityInitializer entityInitializer = parentAccess.findFirstEntityInitializer();
|
||||
final String propertyName = referencedModelPart.getPartName();
|
||||
final int propertyIndex = getPropertyIndex( parentAccess, propertyName );
|
||||
toBatchLoad.forEach(
|
||||
(entityKey, parentInfos) -> {
|
||||
final SharedSessionContractImplementor session = context.getSession();
|
||||
final Object instance = loadInstance( entityKey, referencedModelPart, session );
|
||||
for ( Object parentInstance : parentInfos ) {
|
||||
for ( ParentInfo parentInfo : parentInfos ) {
|
||||
final Object parentInstance = parentInfo.parentInstance;
|
||||
setInstance(
|
||||
entityInitializer,
|
||||
firstEntityInitializer,
|
||||
referencedModelPart,
|
||||
propertyName,
|
||||
propertyIndex,
|
||||
referencedModelPart.getPartName(),
|
||||
parentInfo.propertyIndex,
|
||||
session,
|
||||
instance,
|
||||
parentInstance,
|
||||
|
|
Loading…
Reference in New Issue