5
5
package org .hibernate .event .internal ;
6
6
7
7
import java .lang .invoke .MethodHandles ;
8
+ import java .util .Map ;
8
9
9
10
import org .hibernate .HibernateException ;
10
11
import org .hibernate .Interceptor ;
15
16
import org .hibernate .collection .spi .PersistentCollection ;
16
17
import org .hibernate .engine .internal .Cascade ;
17
18
import org .hibernate .engine .internal .CascadePoint ;
18
- import org .hibernate .engine .spi .ActionQueue ;
19
19
import org .hibernate .engine .spi .CascadingActions ;
20
20
import org .hibernate .engine .spi .CollectionEntry ;
21
21
import org .hibernate .engine .spi .CollectionKey ;
@@ -143,30 +143,30 @@ void checkForTransientReferences(EventSource session, PersistenceContext persist
143
143
// processed, so that all entities which will be persisted are
144
144
// persistent when we do the check (I wonder if we could move this
145
145
// into Nullability, instead of abusing the Cascade infrastructure)
146
- for ( var me : persistenceContext .reentrantSafeEntityEntries () ) {
147
- final var entry = me .getValue ();
146
+ for ( var entryEntry : persistenceContext .reentrantSafeEntityEntries () ) {
147
+ final var entry = entryEntry .getValue ();
148
148
if ( checkable ( entry ) ) {
149
149
Cascade .cascade (
150
150
CascadingActions .CHECK_ON_FLUSH ,
151
151
CascadePoint .BEFORE_FLUSH ,
152
152
session ,
153
153
entry .getPersister (),
154
- me .getKey (),
154
+ entryEntry .getKey (),
155
155
null
156
156
);
157
157
}
158
158
}
159
159
}
160
160
161
161
private static boolean flushable (EntityEntry entry ) {
162
- final Status status = entry .getStatus ();
162
+ final var status = entry .getStatus ();
163
163
return status == Status .MANAGED
164
164
|| status == Status .SAVING
165
165
|| status == Status .READ_ONLY ; // debatable, see HHH-19398
166
166
}
167
167
168
168
private static boolean checkable (EntityEntry entry ) {
169
- final Status status = entry .getStatus ();
169
+ final var status = entry .getStatus ();
170
170
return status == Status .MANAGED
171
171
|| status == Status .SAVING ;
172
172
}
@@ -228,7 +228,7 @@ private int flushEntities(final FlushEvent event, final PersistenceContext persi
228
228
for ( var me : entityEntries ) {
229
229
// Update the status of the object and if necessary, schedule an update
230
230
final var entry = me .getValue ();
231
- final Status status = entry .getStatus ();
231
+ final var status = entry .getStatus ();
232
232
if ( status != Status .LOADING && status != Status .GONE ) {
233
233
entityEvent = createOrReuseEventInstance ( entityEvent , source , me .getKey (), entry );
234
234
entityEvent .setInstanceGenerationId ( ++eventGenerationId );
@@ -270,74 +270,62 @@ private int flushCollections(final EventSource session, final PersistenceContext
270
270
throws HibernateException {
271
271
LOG .trace ( "Processing unreferenced collections" );
272
272
final var collectionEntries = persistenceContext .getCollectionEntries ();
273
- final int count ;
274
- if ( collectionEntries == null ) {
275
- count = 0 ;
276
- }
277
- else {
278
- count = collectionEntries .size ();
279
- final var identityMap =
280
- (InstanceIdentityMap <PersistentCollection <?>, CollectionEntry >)
281
- collectionEntries ;
282
- for ( var me : identityMap .toArray () ) {
283
- final var ce = me .getValue ();
284
- if ( !ce .isReached () && !ce .isIgnore () ) {
285
- processUnreachableCollection ( me .getKey (), session );
286
- }
287
- }
288
- }
273
+ final int count = processUnreachableCollections ( session , collectionEntries );
289
274
290
275
// Schedule updates to collections:
291
276
292
277
LOG .trace ( "Scheduling collection removes/(re)creates/updates" );
293
278
final var actionQueue = session .getActionQueue ();
294
279
final var interceptor = session .getInterceptor ();
295
280
persistenceContext .forEachCollectionEntry (
296
- (coll , ce ) -> {
297
- if ( ce .isDorecreate () ) {
298
- interceptor .onCollectionRecreate ( coll , ce .getCurrentKey () );
281
+ (collection , collectionEntry ) -> {
282
+ if ( collectionEntry .isDorecreate () ) {
283
+ final var currentKey = collectionEntry .getCurrentKey ();
284
+ interceptor .onCollectionRecreate ( collection , currentKey );
299
285
actionQueue .addAction (
300
286
new CollectionRecreateAction (
301
- coll ,
302
- ce .getCurrentPersister (),
303
- ce . getCurrentKey () ,
287
+ collection ,
288
+ collectionEntry .getCurrentPersister (),
289
+ currentKey ,
304
290
session
305
291
)
306
292
);
307
293
}
308
- if ( ce .isDoremove () ) {
309
- interceptor .onCollectionRemove ( coll , ce .getLoadedKey () );
310
- if ( !skipRemoval ( session , ce .getLoadedPersister (), ce .getLoadedKey () ) ) {
294
+ if ( collectionEntry .isDoremove () ) {
295
+ final var loadedKey = collectionEntry .getLoadedKey ();
296
+ interceptor .onCollectionRemove ( collection , loadedKey );
297
+ if ( !skipRemoval ( session , collectionEntry .getLoadedPersister (), loadedKey ) ) {
311
298
actionQueue .addAction (
312
299
new CollectionRemoveAction (
313
- coll ,
314
- ce .getLoadedPersister (),
315
- ce . getLoadedKey () ,
316
- ce .isSnapshotEmpty ( coll ),
300
+ collection ,
301
+ collectionEntry .getLoadedPersister (),
302
+ loadedKey ,
303
+ collectionEntry .isSnapshotEmpty ( collection ),
317
304
session
318
305
)
319
306
);
320
307
}
321
308
}
322
- if ( ce .isDoupdate () ) {
323
- interceptor .onCollectionUpdate ( coll , ce .getLoadedKey () );
309
+ if ( collectionEntry .isDoupdate () ) {
310
+ final var loadedKey = collectionEntry .getLoadedKey ();
311
+ interceptor .onCollectionUpdate ( collection , loadedKey );
324
312
actionQueue .addAction (
325
313
new CollectionUpdateAction (
326
- coll ,
327
- ce .getLoadedPersister (),
328
- ce . getLoadedKey () ,
329
- ce .isSnapshotEmpty ( coll ),
314
+ collection ,
315
+ collectionEntry .getLoadedPersister (),
316
+ loadedKey ,
317
+ collectionEntry .isSnapshotEmpty ( collection ),
330
318
session
331
319
)
332
320
);
333
321
}
334
322
// todo : I'm not sure the !wasInitialized part should really be part of this check
335
- if ( !coll .wasInitialized () && coll .hasQueuedOperations () ) {
323
+ if ( !collection .wasInitialized () && collection .hasQueuedOperations () ) {
336
324
actionQueue .addAction (
337
325
new QueuedOperationCollectionAction (
338
- coll ,
339
- ce .getLoadedPersister (),
340
- ce .getLoadedKey (),
326
+ collection ,
327
+ collectionEntry .getLoadedPersister (),
328
+ collectionEntry .getLoadedKey (),
341
329
session
342
330
)
343
331
);
@@ -349,6 +337,27 @@ private int flushCollections(final EventSource session, final PersistenceContext
349
337
return count ;
350
338
}
351
339
340
+ private static int processUnreachableCollections (
341
+ EventSource session ,
342
+ Map <PersistentCollection <?>, CollectionEntry > collectionEntries ) {
343
+ if ( collectionEntries == null ) {
344
+ return 0 ;
345
+ }
346
+ else {
347
+ final int count = collectionEntries .size ();
348
+ final var identityMap =
349
+ (InstanceIdentityMap <PersistentCollection <?>, CollectionEntry >)
350
+ collectionEntries ;
351
+ for ( var entry : identityMap .toArray () ) {
352
+ final var collectionEntry = entry .getValue ();
353
+ if ( !collectionEntry .isReached () && !collectionEntry .isIgnore () ) {
354
+ processUnreachableCollection ( entry .getKey (), session );
355
+ }
356
+ }
357
+ return count ;
358
+ }
359
+ }
360
+
352
361
/**
353
362
* Execute all SQL (and second-level cache updates) in a special order so that foreign-key constraints cannot
354
363
* be violated: <ol>
@@ -375,7 +384,7 @@ protected void performExecutions(EventSource session) {
375
384
persistenceContext .setFlushing ( true );
376
385
// we need to lock the collection caches before executing entity inserts/updates
377
386
// in order to account for bidirectional associations
378
- final ActionQueue actionQueue = session .getActionQueue ();
387
+ final var actionQueue = session .getActionQueue ();
379
388
actionQueue .prepareActions ();
380
389
actionQueue .executeActions ();
381
390
}
@@ -410,26 +419,27 @@ protected void postFlush(SessionImplementor session) throws HibernateException {
410
419
persistenceContext .forEachCollectionEntry (
411
420
(persistentCollection , collectionEntry ) -> {
412
421
collectionEntry .postFlush ( persistentCollection );
413
- final Object key ;
414
- if ( collectionEntry .getLoadedPersister () == null || ( key = collectionEntry .getLoadedKey () ) == null ) {
422
+ final var loadedPersister = collectionEntry .getLoadedPersister ();
423
+ final Object key = collectionEntry .getLoadedKey ();
424
+ if ( loadedPersister != null && key != null ) {
425
+ //otherwise recreate the mapping between the collection and its key
426
+ final var collectionKey = new CollectionKey ( loadedPersister , key );
427
+ persistenceContext .addCollectionByKey ( collectionKey , persistentCollection );
428
+ }
429
+ else {
415
430
//if the collection is dereferenced, unset its session reference and remove from the session cache
416
431
//iter.remove(); //does not work, since the entrySet is not backed by the set
417
432
persistentCollection .unsetSession ( session );
418
433
persistenceContext .removeCollectionEntry ( persistentCollection );
419
434
}
420
- else {
421
- //otherwise recreate the mapping between the collection and its key
422
- final CollectionKey collectionKey =
423
- new CollectionKey ( collectionEntry .getLoadedPersister (), key );
424
- persistenceContext .addCollectionByKey ( collectionKey , persistentCollection );
425
- }
426
435
},
427
436
true
428
437
);
429
438
}
430
439
431
440
protected void postPostFlush (SessionImplementor session ) {
432
- session .getInterceptor ().postFlush ( session .getPersistenceContextInternal ().managedEntitiesIterator () );
441
+ session .getInterceptor ()
442
+ .postFlush ( session .getPersistenceContextInternal ().managedEntitiesIterator () );
433
443
}
434
444
435
445
}
0 commit comments