1111import org .hibernate .bytecode .enhance .spi .interceptor .EnhancementAsProxyLazinessInterceptor ;
1212import org .hibernate .engine .spi .EntityHolder ;
1313import org .hibernate .engine .spi .EntityKey ;
14- import org .hibernate .engine .spi .PersistenceContext ;
1514import org .hibernate .engine .spi .SharedSessionContractImplementor ;
1615import org .hibernate .metamodel .mapping .AttributeMapping ;
1716import org .hibernate .metamodel .mapping .EntityMappingType ;
1817import org .hibernate .metamodel .mapping .internal .ToOneAttributeMapping ;
1918import org .hibernate .persister .entity .EntityPersister ;
20- import org .hibernate .proxy .HibernateProxy ;
2119import org .hibernate .proxy .LazyInitializer ;
2220import org .hibernate .spi .NavigablePath ;
2321import org .hibernate .sql .results .graph .AssemblerCreationState ;
@@ -39,7 +37,8 @@ public abstract class AbstractBatchEntitySelectFetchInitializer<Data extends Abs
3937
4038 protected final EntityInitializer <InitializerData > owningEntityInitializer ;
4139
42- public static abstract class AbstractBatchEntitySelectFetchInitializerData extends EntitySelectFetchInitializerData {
40+ public static abstract class AbstractBatchEntitySelectFetchInitializerData
41+ extends EntitySelectFetchInitializerData {
4342 final boolean batchDisabled ;
4443
4544 // per-row state
@@ -48,10 +47,11 @@ public static abstract class AbstractBatchEntitySelectFetchInitializerData exten
4847 public AbstractBatchEntitySelectFetchInitializerData (
4948 AbstractBatchEntitySelectFetchInitializer <?> initializer ,
5049 RowProcessingState rowProcessingState ) {
51- super ( initializer , rowProcessingState );
50+ super ( rowProcessingState );
5251
5352 batchDisabled = rowProcessingState .isScrollResult ()
54- || !rowProcessingState .getLoadQueryInfluencers ().effectivelyBatchLoadable ( initializer .toOneMapping .getEntityMappingType ().getEntityPersister () );
53+ || !rowProcessingState .getLoadQueryInfluencers ()
54+ .effectivelyBatchLoadable ( initializer .toOneMapping .getEntityMappingType ().getEntityPersister () );
5555 }
5656 }
5757
@@ -65,66 +65,64 @@ public AbstractBatchEntitySelectFetchInitializer(
6565 AssemblerCreationState creationState ) {
6666 super ( parent , toOneMapping , fetchedNavigable , concreteDescriptor , keyResult , affectedByFilter , creationState );
6767 //noinspection unchecked
68- this .owningEntityInitializer = (EntityInitializer <InitializerData >) Initializer .findOwningEntityInitializer ( parent );
68+ this .owningEntityInitializer =
69+ (EntityInitializer <InitializerData >)
70+ Initializer .findOwningEntityInitializer ( parent );
6971 assert owningEntityInitializer != null : "This initializer requires an owning parent entity initializer" ;
7072 }
7173
7274 protected abstract void registerResolutionListener (Data data );
7375
7476 @ Override
7577 public void resolveKey (Data data ) {
76- if ( data .getState () != State .UNINITIALIZED ) {
77- return ;
78- }
79-
80- data .entityKey = null ;
81- data .setInstance ( null );
82- final RowProcessingState rowProcessingState = data .getRowProcessingState ();
83- //noinspection unchecked
84- final Initializer <InitializerData > initializer = (Initializer <InitializerData >) keyAssembler .getInitializer ();
85- if ( initializer != null ) {
86- final InitializerData subData = initializer .getData ( rowProcessingState );
87- initializer .resolveKey ( subData );
88- data .entityIdentifier = null ;
89- data .setState ( subData .getState () == State .MISSING ? State .MISSING : State .KEY_RESOLVED );
90- }
91- else {
92- data .entityIdentifier = keyAssembler .assemble ( rowProcessingState );
93- data .setState ( data .entityIdentifier == null ? State .MISSING : State .KEY_RESOLVED );
78+ if ( data .getState () == State .UNINITIALIZED ) {
79+ data .entityKey = null ;
80+ data .setInstance ( null );
81+ final var rowProcessingState = data .getRowProcessingState ();
82+ //noinspection unchecked
83+ final Initializer <InitializerData > initializer = (Initializer <InitializerData >) keyAssembler .getInitializer ();
84+ if ( initializer != null ) {
85+ final InitializerData subData = initializer .getData ( rowProcessingState );
86+ initializer .resolveKey ( subData );
87+ data .entityIdentifier = null ;
88+ data .setState ( subData .getState () == State .MISSING ? State .MISSING : State .KEY_RESOLVED );
89+ }
90+ else {
91+ data .entityIdentifier = keyAssembler .assemble ( rowProcessingState );
92+ data .setState ( data .entityIdentifier == null ? State .MISSING : State .KEY_RESOLVED );
93+ }
9494 }
9595 }
9696
9797 @ Override
9898 public void resolveInstance (Data data ) {
99- if ( data .getState () != State .KEY_RESOLVED ) {
100- return ;
101- }
102-
103- data .setState ( State .RESOLVED );
104- final RowProcessingState rowProcessingState = data .getRowProcessingState ();
105- if ( data .entityIdentifier == null ) {
106- // entityIdentifier can be null if the identifier is based on an initializer
107- data .entityIdentifier = keyAssembler .assemble ( rowProcessingState );
99+ if ( data .getState () == State .KEY_RESOLVED ) {
100+ data .setState ( State .RESOLVED );
101+ final var rowProcessingState = data .getRowProcessingState ();
108102 if ( data .entityIdentifier == null ) {
109- data .entityKey = null ;
110- data .setInstance ( null );
111- data .setState ( State .MISSING );
112- return ;
103+ // entityIdentifier can be null if the identifier is based on an initializer
104+ data .entityIdentifier = keyAssembler .assemble ( rowProcessingState );
105+ if ( data .entityIdentifier == null ) {
106+ data .entityKey = null ;
107+ data .setInstance ( null );
108+ data .setState ( State .MISSING );
109+ return ;
110+ }
113111 }
112+ resolveInstanceFromIdentifier ( data );
114113 }
115- resolveInstanceFromIdentifier ( data );
116114 }
117115
118116 protected void resolveInstanceFromIdentifier (Data data ) {
119117 if ( data .batchDisabled ) {
120- initialize ( data );
118+ initializeIfNecessary ( data );
121119 }
122120 else {
123121 data .entityKey = new EntityKey ( data .entityIdentifier , concreteDescriptor );
124122 data .setInstance ( getExistingInitializedInstance ( data ) );
125123 if ( data .getInstance () == null ) {
126- // need to add the key to the batch queue only when the entity has not been already loaded or
127- // there isn't another initializer that is loading it
124+ // need to add the key to the batch queue only when the entity has not
125+ // already been loaded or there's no other initializer that's loading it
128126 registerToBatchFetchQueue ( data );
129127 }
130128 }
@@ -136,87 +134,92 @@ public void resolveInstance(Object instance, Data data) {
136134 data .setState ( State .MISSING );
137135 data .entityKey = null ;
138136 data .setInstance ( null );
139- return ;
140137 }
141- final RowProcessingState rowProcessingState = data .getRowProcessingState ();
142- // Only need to extract the identifier if the identifier has a many to one
143- final LazyInitializer lazyInitializer = extractLazyInitializer ( instance );
144- data .entityKey = null ;
145- data .entityIdentifier = null ;
146- if ( lazyInitializer == null ) {
147- // Entity is most probably initialized
148- data .setInstance ( instance );
149- if ( concreteDescriptor .getBytecodeEnhancementMetadata ().isEnhancedForLazyLoading ()
150- && isPersistentAttributeInterceptable ( instance )
151- && getAttributeInterceptor ( instance )
152- instanceof EnhancementAsProxyLazinessInterceptor enhancementInterceptor ) {
153- if ( enhancementInterceptor .isInitialized () ) {
154- data .setState ( State .INITIALIZED );
138+ else {
139+ final var rowProcessingState = data .getRowProcessingState ();
140+ // Only need to extract the identifier if the identifier has a many-to-one
141+ final LazyInitializer lazyInitializer = extractLazyInitializer ( instance );
142+ data .entityKey = null ;
143+ data .entityIdentifier = null ;
144+ if ( lazyInitializer == null ) {
145+ // Entity is most probably initialized
146+ data .setInstance ( instance );
147+ if ( concreteDescriptor .getBytecodeEnhancementMetadata ().isEnhancedForLazyLoading ()
148+ && isPersistentAttributeInterceptable ( instance )
149+ && getAttributeInterceptor ( instance )
150+ instanceof EnhancementAsProxyLazinessInterceptor enhancementInterceptor ) {
151+ if ( enhancementInterceptor .isInitialized () ) {
152+ data .setState ( State .INITIALIZED );
153+ }
154+ else {
155+ data .setState ( State .RESOLVED );
156+ data .entityIdentifier = enhancementInterceptor .getIdentifier ();
157+ }
158+ if ( keyIsEager && data .entityIdentifier == null ) {
159+ data .entityIdentifier =
160+ concreteDescriptor .getIdentifier ( instance , rowProcessingState .getSession () );
161+ }
155162 }
156163 else {
164+ // If the entity initializer is null, we know the entity is fully initialized.
165+ // Otherwise, it will be initialized by some other initializer.
157166 data .setState ( State .RESOLVED );
158- data .entityIdentifier = enhancementInterceptor .getIdentifier ();
167+ data .entityIdentifier =
168+ concreteDescriptor .getIdentifier ( instance , rowProcessingState .getSession () );
159169 }
160170 }
161- else {
162- // If the entity initializer is null, we know the entity is fully initialized,
163- // otherwise it will be initialized by some other initializer
171+ else if ( lazyInitializer .isUninitialized () ) {
164172 data .setState ( State .RESOLVED );
165- data .entityIdentifier = concreteDescriptor . getIdentifier ( instance , rowProcessingState . getSession () );
173+ data .entityIdentifier = lazyInitializer . getInternalIdentifier ( );
166174 }
167- if ( keyIsEager && data .entityIdentifier == null ) {
168- data .entityIdentifier = concreteDescriptor .getIdentifier ( instance , rowProcessingState .getSession () );
175+ else {
176+ // Entity is initialized
177+ data .setState ( State .INITIALIZED );
178+ if ( keyIsEager ) {
179+ data .entityIdentifier = lazyInitializer .getInternalIdentifier ();
180+ }
181+ data .setInstance ( lazyInitializer .getImplementation () );
182+ }
183+
184+ if ( data .getState () == State .RESOLVED ) {
185+ resolveInstanceFromIdentifier ( data );
169186 }
170- }
171- else if ( lazyInitializer .isUninitialized () ) {
172- data .setState ( State .RESOLVED );
173- data .entityIdentifier = lazyInitializer .getInternalIdentifier ();
174- }
175- else {
176- // Entity is initialized
177- data .setState ( State .INITIALIZED );
178187 if ( keyIsEager ) {
179- data .entityIdentifier = lazyInitializer .getInternalIdentifier ();
188+ final Initializer <?> initializer = keyAssembler .getInitializer ();
189+ assert initializer != null ;
190+ initializer .resolveInstance ( data .entityIdentifier , rowProcessingState );
191+ }
192+ else if ( rowProcessingState .needsResolveState () ) {
193+ // Resolve the state of the identifier if result caching is enabled and this is not a query cache hit
194+ keyAssembler .resolveState ( rowProcessingState );
180195 }
181- data .setInstance ( lazyInitializer .getImplementation () );
182- }
183-
184- if ( data .getState () == State .RESOLVED ) {
185- resolveInstanceFromIdentifier ( data );
186- }
187- if ( keyIsEager ) {
188- final Initializer <?> initializer = keyAssembler .getInitializer ();
189- assert initializer != null ;
190- initializer .resolveInstance ( data .entityIdentifier , rowProcessingState );
191- }
192- else if ( rowProcessingState .needsResolveState () ) {
193- // Resolve the state of the identifier if result caching is enabled and this is not a query cache hit
194- keyAssembler .resolveState ( rowProcessingState );
195196 }
196197 }
197198
198199 @ Override
199200 public void initializeInstance (Data data ) {
200- if ( data .getState () != State .RESOLVED ) {
201- return ;
202- }
203- data .setState ( State .INITIALIZED );
204- if ( data .batchDisabled ) {
205- Hibernate .initialize ( data .getInstance () );
201+ if ( data .getState () == State .RESOLVED ) {
202+ data .setState ( State .INITIALIZED );
203+ if ( data .batchDisabled ) {
204+ Hibernate .initialize ( data .getInstance () );
205+ }
206206 }
207207 }
208208
209209 protected Object getExistingInitializedInstance (Data data ) {
210- final SharedSessionContractImplementor session = data .getRowProcessingState ().getSession ();
211- final PersistenceContext persistenceContext = session .getPersistenceContextInternal ();
212- final EntityHolder holder = persistenceContext .getEntityHolder ( data .entityKey );
210+ final EntityHolder holder =
211+ data .getRowProcessingState ().getSession ()
212+ .getPersistenceContextInternal ()
213+ .getEntityHolder ( data .entityKey );
213214 if ( holder != null && holder .getEntity () != null && holder .isEventuallyInitialized () ) {
214215 return holder .getEntity ();
215216 }
216- // we need to register a resolution listener only if there is not an already initialized instance
217- // or an instance that another initializer is loading
218- registerResolutionListener ( data );
219- return null ;
217+ else {
218+ // we need to register a resolution listener only if there is not an already initialized instance
219+ // or an instance that another initializer is loading
220+ registerResolutionListener ( data );
221+ return null ;
222+ }
220223 }
221224
222225 protected void registerToBatchFetchQueue (Data data ) {
@@ -238,7 +241,7 @@ public void initializeInstanceFromParent(Object parentInstance, Data data) {
238241 data .setState ( State .MISSING );
239242 }
240243 else {
241- final LazyInitializer lazyInitializer = HibernateProxy . extractLazyInitializer ( instance );
244+ final LazyInitializer lazyInitializer = extractLazyInitializer ( instance );
242245 if ( lazyInitializer != null && lazyInitializer .isUninitialized () ) {
243246 data .entityKey = new EntityKey ( lazyInitializer .getInternalIdentifier (), concreteDescriptor );
244247 registerToBatchFetchQueue ( data );
@@ -259,40 +262,35 @@ protected static Object loadInstance(
259262 toOneMapping .isInternalLoadNullable ()
260263 );
261264 if ( instance == null ) {
262- if ( toOneMapping .getNotFoundAction () != NotFoundAction .IGNORE ) {
263- if ( affectedByFilter ) {
264- throw new EntityFilterException (
265- entityKey .getEntityName (),
266- entityKey .getIdentifier (),
267- toOneMapping .getNavigableRole ().getFullPath ()
268- );
269- }
270- if ( toOneMapping .getNotFoundAction () == NotFoundAction .EXCEPTION ) {
271- throw new FetchNotFoundException ( entityKey .getEntityName (), entityKey .getIdentifier () );
272- }
273- }
265+ handleNotFound ( entityKey , toOneMapping , affectedByFilter );
274266 }
275267 return instance ;
276268 }
277269
270+ private static void handleNotFound (EntityKey entityKey , ToOneAttributeMapping toOneMapping , boolean affectedByFilter ) {
271+ final NotFoundAction notFoundAction = toOneMapping .getNotFoundAction (); // can be null
272+ if ( affectedByFilter ) {
273+ if ( notFoundAction != NotFoundAction .IGNORE ) {
274+ throw new EntityFilterException ( entityKey .getEntityName (), entityKey .getIdentifier (),
275+ toOneMapping .getNavigableRole ().getFullPath () );
276+ }
277+ }
278+ else {
279+ if ( notFoundAction == NotFoundAction .EXCEPTION ) {
280+ throw new FetchNotFoundException ( entityKey .getEntityName (), entityKey .getIdentifier () );
281+ }
282+ }
283+ }
284+
278285 protected AttributeMapping [] getParentEntityAttributes (String attributeName ) {
279286 final EntityPersister entityDescriptor = owningEntityInitializer .getEntityDescriptor ();
280- final AttributeMapping [] parentEntityAttributes = new AttributeMapping [
281- entityDescriptor .getRootEntityDescriptor ()
282- .getSubclassEntityNames ()
283- .size ()
284- ];
285- parentEntityAttributes [entityDescriptor .getSubclassId ()] = getParentEntityAttribute (
286- entityDescriptor ,
287- toOneMapping ,
288- attributeName
289- );
290- for ( EntityMappingType subMappingType : entityDescriptor .getSubMappingTypes () ) {
291- parentEntityAttributes [subMappingType .getSubclassId ()] = getParentEntityAttribute (
292- subMappingType ,
293- toOneMapping ,
294- attributeName
295- );
287+ final int size = entityDescriptor .getRootEntityDescriptor ().getSubclassEntityNames ().size ();
288+ final AttributeMapping [] parentEntityAttributes = new AttributeMapping [size ];
289+ parentEntityAttributes [entityDescriptor .getSubclassId ()] =
290+ getParentEntityAttribute ( entityDescriptor , toOneMapping , attributeName );
291+ for ( var subMappingType : entityDescriptor .getSubMappingTypes () ) {
292+ parentEntityAttributes [subMappingType .getSubclassId ()] =
293+ getParentEntityAttribute ( subMappingType , toOneMapping , attributeName );
296294 }
297295 return parentEntityAttributes ;
298296 }
@@ -302,8 +300,9 @@ protected static AttributeMapping getParentEntityAttribute(
302300 ToOneAttributeMapping referencedModelPart ,
303301 String attributeName ) {
304302 final AttributeMapping parentAttribute = subMappingType .findAttributeMapping ( attributeName );
305- if ( parentAttribute != null && parentAttribute .getDeclaringType () == referencedModelPart .getDeclaringType ()
306- .findContainingEntityMapping () ) {
303+ if ( parentAttribute != null
304+ && parentAttribute .getDeclaringType ()
305+ == referencedModelPart .getDeclaringType ().findContainingEntityMapping () ) {
307306 // These checks are needed to avoid setting the instance using the wrong (child's) model part or
308307 // setting it multiple times in case parent and child share the same attribute name for the association.
309308 return parentAttribute ;
0 commit comments