14
14
import org .hibernate .engine .spi .PersistentAttributeInterceptor ;
15
15
import org .hibernate .internal .CoreLogging ;
16
16
import org .hibernate .internal .CoreMessageLogger ;
17
+ import org .hibernate .internal .util .collections .InstanceIdentityStore ;
18
+ import org .hibernate .persister .entity .EntityPersister ;
17
19
18
20
import java .io .IOException ;
19
21
import java .io .ObjectInputStream ;
@@ -49,7 +51,8 @@ public class EntityEntryContext {
49
51
50
52
private final transient PersistenceContext persistenceContext ;
51
53
52
- private transient IdentityHashMap <ManagedEntity ,ImmutableManagedEntityHolder > immutableManagedEntityXref ;
54
+ private transient InstanceIdentityStore <ImmutableManagedEntityHolder > immutableManagedEntityXref ;
55
+ private transient int currentInstanceId ;
53
56
54
57
private transient ManagedEntity head ;
55
58
private transient ManagedEntity tail ;
@@ -107,21 +110,19 @@ public void addEntityEntry(Object entity, EntityEntry entityEntry) {
107
110
else {
108
111
// Create a holder for PersistenceContext-related data.
109
112
managedEntity = new ImmutableManagedEntityHolder ( managed );
110
- if ( immutableManagedEntityXref == null ) {
111
- immutableManagedEntityXref = new IdentityHashMap <>();
113
+ if ( !isReferenceCachingEnabled ( entityEntry .getPersister () ) ) {
114
+ managed .$$_hibernate_setInstanceId ( nextManagedEntityInstanceId () );
115
+ putImmutableManagedEntity ( managed , (ImmutableManagedEntityHolder ) managedEntity );
116
+ }
117
+ else {
118
+ // When reference caching is enabled we cannot set the instance-id on the entity instance
119
+ putManagedEntity ( entity , managedEntity );
112
120
}
113
- immutableManagedEntityXref .put (
114
- managed ,
115
- (ImmutableManagedEntityHolder ) managedEntity
116
- );
117
121
}
118
122
}
119
123
else {
120
- if ( nonEnhancedEntityXref == null ) {
121
- nonEnhancedEntityXref = new IdentityHashMap <>();
122
- }
123
124
managedEntity = new ManagedEntityImpl ( entity );
124
- nonEnhancedEntityXref . put ( entity , managedEntity );
125
+ putManagedEntity ( entity , managedEntity );
125
126
}
126
127
}
127
128
@@ -155,6 +156,12 @@ public void addEntityEntry(Object entity, EntityEntry entityEntry) {
155
156
}
156
157
}
157
158
159
+ private static boolean isReferenceCachingEnabled (EntityPersister persister ) {
160
+ // Immutable entities which can use reference caching are treated as non-enhanced entities, as setting
161
+ // the instance-id on them would be problematic in different sessions
162
+ return persister .canUseReferenceCacheEntries () && persister .canReadFromCache ();
163
+ }
164
+
158
165
private ManagedEntity getAssociatedManagedEntity (Object entity ) {
159
166
if ( isManagedEntity ( entity ) ) {
160
167
final ManagedEntity managedEntity = asManagedEntity ( entity );
@@ -170,20 +177,35 @@ private ManagedEntity getAssociatedManagedEntity(Object entity) {
170
177
? managedEntity // it is associated
171
178
: null ;
172
179
}
173
- else {
174
- // if managedEntity is associated with this EntityEntryContext, then
175
- // it will have an entry in immutableManagedEntityXref and its
176
- // holder will be returned.
180
+ else if ( !isReferenceCachingEnabled ( entityEntry .getPersister () ) ) {
181
+ // if managedEntity is associated with this EntityEntryContext, it may have
182
+ // an entry in immutableManagedEntityXref and its holder will be returned.
177
183
return immutableManagedEntityXref != null
178
- ? immutableManagedEntityXref .get ( managedEntity )
184
+ ? immutableManagedEntityXref .get ( managedEntity . $$_hibernate_getInstanceId (), managedEntity )
179
185
: null ;
180
186
}
181
187
}
182
- else {
183
- return nonEnhancedEntityXref != null
184
- ? nonEnhancedEntityXref .get ( entity )
185
- : null ;
188
+ return nonEnhancedEntityXref != null
189
+ ? nonEnhancedEntityXref .get ( entity )
190
+ : null ;
191
+ }
192
+
193
+ private void putManagedEntity (Object entity , ManagedEntity managedEntity ) {
194
+ if ( nonEnhancedEntityXref == null ) {
195
+ nonEnhancedEntityXref = new IdentityHashMap <>();
186
196
}
197
+ nonEnhancedEntityXref .put ( entity , managedEntity );
198
+ }
199
+
200
+ private int nextManagedEntityInstanceId () {
201
+ return currentInstanceId ++;
202
+ }
203
+
204
+ private void putImmutableManagedEntity (ManagedEntity managed , ImmutableManagedEntityHolder holder ) {
205
+ if ( immutableManagedEntityXref == null ) {
206
+ immutableManagedEntityXref = new InstanceIdentityStore <>();
207
+ }
208
+ immutableManagedEntityXref .put ( managed , holder );
187
209
}
188
210
189
211
private void checkNotAssociatedWithOtherPersistenceContextIfMutable (ManagedEntity managedEntity ) {
@@ -253,12 +275,16 @@ public EntityEntry removeEntityEntry(Object entity) {
253
275
254
276
dirty = true ;
255
277
256
- if (managedEntity instanceof ImmutableManagedEntityHolder ) {
257
- assert entity == ( (ImmutableManagedEntityHolder ) managedEntity ).managedEntity ;
258
- immutableManagedEntityXref .remove ( entity );
259
-
278
+ if ( managedEntity instanceof ImmutableManagedEntityHolder holder ) {
279
+ assert entity == holder .managedEntity ;
280
+ if ( !isReferenceCachingEnabled ( holder .$$_hibernate_getEntityEntry ().getPersister () ) ) {
281
+ immutableManagedEntityXref .remove ( managedEntity .$$_hibernate_getInstanceId (), entity );
282
+ }
283
+ else {
284
+ nonEnhancedEntityXref .remove ( entity );
285
+ }
260
286
}
261
- else if ( ! ( isManagedEntity ( entity ) ) ) {
287
+ else if ( !isManagedEntity ( entity ) ) {
262
288
nonEnhancedEntityXref .remove ( entity );
263
289
}
264
290
@@ -387,6 +413,7 @@ public void clear() {
387
413
count = 0 ;
388
414
389
415
reentrantSafeEntries = null ;
416
+ currentInstanceId = 0 ;
390
417
}
391
418
392
419
private static void clearManagedEntity (final ManagedEntity node ) {
@@ -478,30 +505,26 @@ public static EntityEntryContext deserialize(ObjectInputStream ois, StatefulPers
478
505
479
506
final ManagedEntity managedEntity ;
480
507
if ( isEnhanced ) {
508
+ final ManagedEntity castedEntity = asManagedEntity ( entity );
481
509
if ( entry .getPersister ().isMutable () ) {
482
- managedEntity = ManagedTypeHelper . asManagedEntity ( entity ) ;
510
+ managedEntity = castedEntity ;
483
511
}
484
512
else {
485
- final ManagedEntity castedEntity = asManagedEntity ( entity );
486
513
managedEntity = new ImmutableManagedEntityHolder ( castedEntity );
487
- if ( context .immutableManagedEntityXref == null ) {
488
- context .immutableManagedEntityXref =
489
- new IdentityHashMap <>();
514
+ if ( !isReferenceCachingEnabled ( entry .getPersister () ) ) {
515
+ castedEntity .$$_hibernate_setInstanceId ( context .nextManagedEntityInstanceId () );
516
+ context .putImmutableManagedEntity ( castedEntity , (ImmutableManagedEntityHolder ) managedEntity );
517
+ }
518
+ else {
519
+ context .putManagedEntity ( entity , castedEntity );
490
520
}
491
- context .immutableManagedEntityXref .put (
492
- castedEntity ,
493
- (ImmutableManagedEntityHolder ) managedEntity
494
-
495
- );
496
521
}
497
522
}
498
523
else {
499
524
managedEntity = new ManagedEntityImpl ( entity );
500
- if ( context .nonEnhancedEntityXref == null ) {
501
- context .nonEnhancedEntityXref = new IdentityHashMap <>();
502
- }
503
- context .nonEnhancedEntityXref .put ( entity , managedEntity );
525
+ context .putManagedEntity ( entity , managedEntity );
504
526
}
527
+
505
528
managedEntity .$$_hibernate_setEntityEntry ( entry );
506
529
507
530
if ( previous == null ) {
@@ -605,6 +628,15 @@ public ManagedEntityImpl(Object entityInstance) {
605
628
public void $$_hibernate_setPreviousManagedEntity (ManagedEntity previous ) {
606
629
this .previous = previous ;
607
630
}
631
+
632
+ @ Override
633
+ public int $$_hibernate_getInstanceId () {
634
+ return -1 ;
635
+ }
636
+
637
+ @ Override
638
+ public void $$_hibernate_setInstanceId (int id ) {
639
+ }
608
640
}
609
641
610
642
private static class ImmutableManagedEntityHolder implements ManagedEntity {
@@ -693,6 +725,16 @@ private boolean canClearEntityEntryReference() {
693
725
return !(entityEntry instanceof ImmutableEntityEntry )
694
726
|| !entityEntry .getPersister ().canUseReferenceCacheEntries ();
695
727
}
728
+
729
+ @ Override
730
+ public int $$_hibernate_getInstanceId () {
731
+ return managedEntity .$$_hibernate_getInstanceId ();
732
+ }
733
+
734
+ @ Override
735
+ public void $$_hibernate_setInstanceId (int id ) {
736
+ managedEntity .$$_hibernate_setInstanceId ( id );
737
+ }
696
738
}
697
739
698
740
/**
0 commit comments