8
8
import org .hibernate .LockMode ;
9
9
import org .hibernate .LockOptions ;
10
10
import org .hibernate .engine .jdbc .spi .JdbcServices ;
11
+ import org .hibernate .engine .spi .BatchFetchQueue ;
11
12
import org .hibernate .engine .spi .EntityKey ;
13
+ import org .hibernate .engine .spi .PersistenceContext ;
12
14
import org .hibernate .engine .spi .SessionFactoryImplementor ;
13
15
import org .hibernate .event .spi .EventSource ;
14
16
import org .hibernate .loader .ast .spi .MultiIdEntityLoader ;
@@ -164,11 +166,32 @@ protected static LockOptions lockOptions(MultiIdLoadOptions loadOptions) {
164
166
165
167
protected abstract int maxBatchSize (Object [] ids , MultiIdLoadOptions loadOptions );
166
168
167
- protected abstract void handleResults (
169
+ protected void handleResults (
168
170
MultiIdLoadOptions loadOptions ,
169
171
EventSource session ,
170
172
List <Integer > elementPositionsLoadedByBatch ,
171
- List <Object > result );
173
+ List <Object > results ) {
174
+ final PersistenceContext persistenceContext = session .getPersistenceContext ();
175
+ for ( Integer position : elementPositionsLoadedByBatch ) {
176
+ // the element value at this position in the results List should be
177
+ // the EntityKey for that entity - reuse it
178
+ final EntityKey entityKey = (EntityKey ) results .get ( position );
179
+ session .getPersistenceContextInternal ().getBatchFetchQueue ().removeBatchLoadableEntityKey ( entityKey );
180
+ final Object entity = persistenceContext .getEntity ( entityKey );
181
+ final Object result ;
182
+ if ( entity == null
183
+ // the entity is locally deleted, and the options ask that we not return such entities
184
+ || !loadOptions .isReturnOfDeletedEntitiesEnabled ()
185
+ && persistenceContext .getEntry ( entity ).getStatus ().isDeletedOrGone () ) {
186
+ result = null ;
187
+ }
188
+ else {
189
+ result = persistenceContext .proxyFor ( entity );
190
+ }
191
+ results .set ( position , result );
192
+ }
193
+ }
194
+
172
195
173
196
protected abstract void loadEntitiesById (
174
197
List <Object > idsInBatch ,
@@ -192,39 +215,36 @@ private boolean isLoadFromCaches(
192
215
MultiIdLoadOptions loadOptions ,
193
216
EntityKey entityKey ,
194
217
LockOptions lockOptions ,
195
- List <Object > result , int i ,
218
+ List <Object > results , int i ,
196
219
EventSource session ) {
197
- Object managedEntity = null ;
198
220
199
221
if ( loadOptions .isSessionCheckingEnabled () ) {
200
222
// look for it in the Session first
201
- final PersistenceContextEntry persistenceContextEntry =
223
+ final PersistenceContextEntry entry =
202
224
loadFromSessionCache ( entityKey , lockOptions , GET , session );
203
- managedEntity = persistenceContextEntry .entity ();
204
-
205
- if ( managedEntity != null
206
- && !loadOptions .isReturnOfDeletedEntitiesEnabled ()
207
- && !persistenceContextEntry .isManaged () ) {
208
- // put a null in the result
209
- result .add ( i , null );
225
+ final Object entity = entry .entity ();
226
+ if ( entity != null ) {
227
+ // put a null in the results
228
+ final Object result =
229
+ loadOptions .isReturnOfDeletedEntitiesEnabled ()
230
+ || entry .isManaged ()
231
+ ? entity : null ;
232
+ results .add ( i , result );
210
233
return true ;
211
234
}
212
235
}
213
236
214
- if ( managedEntity == null
215
- && loadOptions .isSecondLevelCacheCheckingEnabled () ) {
216
- // look for it in the SessionFactory
217
- final EntityPersister persister = getLoadable ().getEntityPersister ();
218
- managedEntity = session .loadFromSecondLevelCache ( persister , entityKey , null , lockOptions .getLockMode () );
237
+ if ( loadOptions .isSecondLevelCacheCheckingEnabled () ) {
238
+ // look for it in the second-level cache
239
+ final Object entity =
240
+ loadFromSecondLevelCache ( entityKey , lockOptions , session );
241
+ if ( entity != null ) {
242
+ results .add ( i , entity );
243
+ return true ;
244
+ }
219
245
}
220
246
221
- if ( managedEntity != null ) {
222
- result .add ( i , managedEntity );
223
- return true ;
224
- }
225
- else {
226
- return false ;
227
- }
247
+ return false ;
228
248
}
229
249
230
250
protected List <T > unorderedMultiLoad (
@@ -238,6 +258,16 @@ protected List<T> unorderedMultiLoad(
238
258
(position , entityKey , resolvedRef ) -> result .add ( (T ) resolvedRef ) );
239
259
if ( !isEmpty ( unresolvableIds ) ) {
240
260
loadEntitiesWithUnresolvedIds ( loadOptions , lockOptions , session , unresolvableIds , result );
261
+ final BatchFetchQueue batchFetchQueue = session .getPersistenceContextInternal ().getBatchFetchQueue ();
262
+ final EntityPersister persister = getLoadable ().getEntityPersister ();
263
+ for ( Object id : unresolvableIds ) {
264
+ // skip any of the null padded ids
265
+ // (actually we could probably even break on the first null)
266
+ if ( id != null ) {
267
+ // found or not, remove the key from the batch-fetch queue
268
+ batchFetchQueue .removeBatchLoadableEntityKey ( session .generateEntityKey ( id , persister ) );
269
+ }
270
+ }
241
271
}
242
272
return result ;
243
273
}
@@ -247,7 +277,7 @@ protected abstract void loadEntitiesWithUnresolvedIds(
247
277
LockOptions lockOptions ,
248
278
EventSource session ,
249
279
Object [] unresolvableIds ,
250
- List <T > result );
280
+ List <T > results );
251
281
252
282
protected final <R > Object [] resolveInCachesIfEnabled (
253
283
Object [] ids ,
@@ -259,7 +289,7 @@ protected final <R> Object[] resolveInCachesIfEnabled(
259
289
// the user requested that we exclude ids corresponding to already managed
260
290
// entities from the generated load SQL. So here we will iterate all
261
291
// incoming id values and see whether it corresponds to an existing
262
- // entity associated with the PC. If it does, we add it to the result
292
+ // entity associated with the PC. If it does, we add it to the results
263
293
// list immediately and remove its id from the group of ids to load.
264
294
// we'll load all of them from the database
265
295
? resolveInCaches ( ids , loadOptions , lockOptions , session , resolutionConsumer )
@@ -319,14 +349,14 @@ private <R> List<Object> loadFromCaches(
319
349
EventSource session ) {
320
350
321
351
// look for it in the Session first
322
- final PersistenceContextEntry persistenceContextEntry =
352
+ final PersistenceContextEntry entry =
323
353
loadFromSessionCache ( entityKey , lockOptions , GET , session );
324
354
final Object sessionEntity ;
325
355
if ( loadOptions .isSessionCheckingEnabled () ) {
326
- sessionEntity = persistenceContextEntry .entity ();
356
+ sessionEntity = entry .entity ();
327
357
if ( sessionEntity != null
328
358
&& !loadOptions .isReturnOfDeletedEntitiesEnabled ()
329
- && !persistenceContextEntry .isManaged () ) {
359
+ && !entry .isManaged () ) {
330
360
resolutionConsumer .consume ( i , entityKey , null );
331
361
return unresolvedIds ;
332
362
}
@@ -335,13 +365,10 @@ private <R> List<Object> loadFromCaches(
335
365
sessionEntity = null ;
336
366
}
337
367
338
- final Object cachedEntity ;
339
- if ( sessionEntity == null && loadOptions .isSecondLevelCacheCheckingEnabled () ) {
340
- cachedEntity = session .loadFromSecondLevelCache ( getLoadable ().getEntityPersister (), entityKey , null , lockOptions .getLockMode () );
341
- }
342
- else {
343
- cachedEntity = sessionEntity ;
344
- }
368
+ final Object cachedEntity =
369
+ sessionEntity == null && loadOptions .isSecondLevelCacheCheckingEnabled ()
370
+ ? loadFromSecondLevelCache ( entityKey , lockOptions , session )
371
+ : sessionEntity ;
345
372
346
373
if ( cachedEntity != null ) {
347
374
//noinspection unchecked
@@ -356,4 +383,8 @@ private <R> List<Object> loadFromCaches(
356
383
return unresolvedIds ;
357
384
}
358
385
386
+ private Object loadFromSecondLevelCache (EntityKey entityKey , LockOptions lockOptions , EventSource session ) {
387
+ final EntityPersister persister = getLoadable ().getEntityPersister ();
388
+ return session .loadFromSecondLevelCache ( persister , entityKey , null , lockOptions .getLockMode () );
389
+ }
359
390
}
0 commit comments