44 */
55package org .hibernate .sql .results .graph .collection .internal ;
66
7+ import java .util .ArrayList ;
8+ import java .util .Collections ;
79import java .util .List ;
810import java .util .function .BiConsumer ;
911
2123import org .hibernate .sql .results .graph .InitializerData ;
2224import org .hibernate .sql .results .graph .InitializerParent ;
2325import org .hibernate .sql .results .graph .collection .LoadingCollectionEntry ;
26+ import org .hibernate .sql .results .graph .entity .EntityInitializer ;
2427import org .hibernate .sql .results .internal .LoadingCollectionEntryImpl ;
2528import org .hibernate .sql .results .jdbc .spi .RowProcessingState ;
2629
@@ -43,6 +46,7 @@ public abstract class AbstractImmediateCollectionInitializer<Data extends Abstra
4346 * refers to the rows entry in the collection. null indicates that the collection is empty
4447 */
4548 protected final @ Nullable DomainResultAssembler <?> collectionValueKeyResultAssembler ;
49+ protected final EntityInitializer <InitializerData > @ Nullable [] grandParentEntityInitializers ;
4650
4751 public static class ImmediateCollectionInitializerData extends CollectionInitializerData {
4852
@@ -84,6 +88,29 @@ public AbstractImmediateCollectionInitializer(
8488 collectionKeyResult == collectionValueKeyResult
8589 ? null
8690 : collectionValueKeyResult .createResultAssembler ( this , creationState );
91+ this .grandParentEntityInitializers = determineGrandParentEntityInitializers ( parent );
92+ }
93+
94+ private static EntityInitializer <InitializerData > @ Nullable [] determineGrandParentEntityInitializers (InitializerParent <?> parent ) {
95+ EntityInitializer <?> parentEntityInitializer = Initializer .findOwningEntityInitializer ( parent );
96+ ArrayList <EntityInitializer <InitializerData >> grandParentEntityInitializers = null ;
97+ while ( parentEntityInitializer != null ) {
98+ parentEntityInitializer = Initializer .findOwningEntityInitializer ( parentEntityInitializer .getParent () );
99+ if ( parentEntityInitializer != null ) {
100+ if ( grandParentEntityInitializers == null ) {
101+ grandParentEntityInitializers = new ArrayList <>();
102+ }
103+ //noinspection unchecked
104+ grandParentEntityInitializers .add ( (EntityInitializer <InitializerData >) parentEntityInitializer );
105+ }
106+ }
107+ if ( grandParentEntityInitializers != null ) {
108+ Collections .reverse ( grandParentEntityInitializers );
109+ }
110+ //noinspection unchecked
111+ return grandParentEntityInitializers == null
112+ ? null
113+ : grandParentEntityInitializers .toArray ( new EntityInitializer [0 ] );
87114 }
88115
89116 @ Override
@@ -253,7 +280,7 @@ public void resolveInstance(Data data) {
253280 if ( existingLoadingEntry != null ) {
254281 data .setCollectionInstance ( existingLoadingEntry .getCollectionInstance () );
255282
256- if ( existingLoadingEntry . getInitializer () == this ) {
283+ if ( shouldContinueLoadingEntry ( existingLoadingEntry , rowProcessingState ) ) {
257284 assert !data .shallowCached ;
258285 // we are responsible for loading the collection values
259286 data .responsibility = (LoadingCollectionEntryImpl ) existingLoadingEntry ;
@@ -326,6 +353,26 @@ else if ( !data.shallowCached ) {
326353 }
327354 }
328355
356+ protected boolean shouldContinueLoadingEntry (LoadingCollectionEntry existingLoadingEntry , RowProcessingState rowProcessingState ) {
357+ if ( existingLoadingEntry .getInitializer () != this ) {
358+ return false ;
359+ }
360+ else {
361+ final Object [] existingGrandParentEntities = existingLoadingEntry .getGrandParentEntities ();
362+ if ( existingGrandParentEntities != null ) {
363+ final Object [] grandParentEntities = determineGrandParentEntities ( rowProcessingState );
364+ assert grandParentEntities != null ;
365+ assert existingGrandParentEntities .length == grandParentEntities .length ;
366+ for ( int i = 0 ; i < existingGrandParentEntities .length ; i ++ ) {
367+ if ( existingGrandParentEntities [i ] != grandParentEntities [i ] ) {
368+ return false ;
369+ }
370+ }
371+ }
372+ return true ;
373+ }
374+ }
375+
329376 protected void initializeShallowCached (Data data ) {
330377 assert data .shallowCached ;
331378 // If this is a query cache hit with the shallow query cache layout,
@@ -423,13 +470,25 @@ private void resolveCollectionContentState(RowProcessingState rowProcessingState
423470 getElementAssembler ().resolveState ( rowProcessingState );
424471 }
425472
473+ protected Object @ Nullable [] determineGrandParentEntities (RowProcessingState rowProcessingState ) {
474+ if ( grandParentEntityInitializers == null ) {
475+ return null ;
476+ }
477+ final Object [] entities = new Object [grandParentEntityInitializers .length ];
478+ for ( int i = 0 ; i < grandParentEntityInitializers .length ; i ++ ) {
479+ entities [i ] = grandParentEntityInitializers [i ].getResolvedInstance ( rowProcessingState );
480+ }
481+ return entities ;
482+ }
483+
426484 protected void takeResponsibility (Data data ) {
427485 data .responsibility =
428486 new LoadingCollectionEntryImpl (
429487 getCollectionAttributeMapping ().getCollectionDescriptor (),
430488 this ,
431489 data .collectionKey .getKey (),
432- data .getCollectionInstance ()
490+ data .getCollectionInstance (),
491+ determineGrandParentEntities ( data .getRowProcessingState () )
433492 );
434493 data .getRowProcessingState ().getJdbcValuesSourceProcessingState ()
435494 .registerLoadingCollection ( data .collectionKey , data .responsibility );
0 commit comments