1414import org .hibernate .engine .spi .PersistentAttributeInterceptor ;
1515import org .hibernate .internal .CoreLogging ;
1616import org .hibernate .internal .CoreMessageLogger ;
17+ import org .hibernate .internal .util .collections .InstanceIdentityMap ;
18+ import org .hibernate .internal .util .collections .StandardStack ;
1719
1820import java .io .IOException ;
1921import java .io .ObjectInputStream ;
@@ -49,7 +51,9 @@ public class EntityEntryContext {
4951
5052 private final transient PersistenceContext persistenceContext ;
5153
52- private transient IdentityHashMap <ManagedEntity ,ImmutableManagedEntityHolder > immutableManagedEntityXref ;
54+ private transient InstanceIdentityMap <ManagedEntity , ImmutableManagedEntityHolder > immutableManagedEntityXref ;
55+ private transient StandardStack <Integer > reusableInstanceIds ;
56+ private transient int currentInstanceId ;
5357
5458 private transient ManagedEntity head ;
5559 private transient ManagedEntity tail ;
@@ -107,13 +111,8 @@ public void addEntityEntry(Object entity, EntityEntry entityEntry) {
107111 else {
108112 // Create a holder for PersistenceContext-related data.
109113 managedEntity = new ImmutableManagedEntityHolder ( managed );
110- if ( immutableManagedEntityXref == null ) {
111- immutableManagedEntityXref = new IdentityHashMap <>();
112- }
113- immutableManagedEntityXref .put (
114- managed ,
115- (ImmutableManagedEntityHolder ) managedEntity
116- );
114+ managed .$$_hibernate_setInstanceId ( nextManagedEntityInstanceId () );
115+ putImmutableManagedEntity ( managed , (ImmutableManagedEntityHolder ) managedEntity );
117116 }
118117 }
119118 else {
@@ -171,9 +170,8 @@ private ManagedEntity getAssociatedManagedEntity(Object entity) {
171170 : null ;
172171 }
173172 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.
173+ // if managedEntity is associated with this EntityEntryContext, it may have
174+ // an entry in immutableManagedEntityXref and its holder will be returned.
177175 return immutableManagedEntityXref != null
178176 ? immutableManagedEntityXref .get ( managedEntity )
179177 : null ;
@@ -186,6 +184,19 @@ private ManagedEntity getAssociatedManagedEntity(Object entity) {
186184 }
187185 }
188186
187+ private int nextManagedEntityInstanceId () {
188+ return reusableInstanceIds != null && !reusableInstanceIds .isEmpty () ?
189+ reusableInstanceIds .pop () :
190+ currentInstanceId ++;
191+ }
192+
193+ private void putImmutableManagedEntity (ManagedEntity managed , ImmutableManagedEntityHolder holder ) {
194+ if ( immutableManagedEntityXref == null ) {
195+ immutableManagedEntityXref = new InstanceIdentityMap <>();
196+ }
197+ immutableManagedEntityXref .put ( managed , holder );
198+ }
199+
189200 private void checkNotAssociatedWithOtherPersistenceContextIfMutable (ManagedEntity managedEntity ) {
190201 // we only have to check mutable managedEntity
191202 final AbstractEntityEntry entityEntry = (AbstractEntityEntry ) managedEntity .$$_hibernate_getEntityEntry ();
@@ -253,12 +264,15 @@ public EntityEntry removeEntityEntry(Object entity) {
253264
254265 dirty = true ;
255266
256- if (managedEntity instanceof ImmutableManagedEntityHolder ) {
257- assert entity == ( (ImmutableManagedEntityHolder ) managedEntity ).managedEntity ;
267+ if ( managedEntity instanceof ImmutableManagedEntityHolder ) {
268+ assert entity == ((ImmutableManagedEntityHolder ) managedEntity ).managedEntity ;
258269 immutableManagedEntityXref .remove ( entity );
259-
270+ if ( reusableInstanceIds == null ) {
271+ reusableInstanceIds = new StandardStack <>();
272+ }
273+ reusableInstanceIds .push ( managedEntity .$$_hibernate_getInstanceId () );
260274 }
261- else if ( ! ( isManagedEntity ( entity ) ) ) {
275+ else if ( !isManagedEntity ( entity ) ) {
262276 nonEnhancedEntityXref .remove ( entity );
263277 }
264278
@@ -387,6 +401,8 @@ public void clear() {
387401 count = 0 ;
388402
389403 reentrantSafeEntries = null ;
404+ currentInstanceId = 0 ;
405+ reusableInstanceIds = null ;
390406 }
391407
392408 private static void clearManagedEntity (final ManagedEntity node ) {
@@ -483,16 +499,9 @@ public static EntityEntryContext deserialize(ObjectInputStream ois, StatefulPers
483499 }
484500 else {
485501 final ManagedEntity castedEntity = asManagedEntity ( entity );
502+ castedEntity .$$_hibernate_setInstanceId ( context .nextManagedEntityInstanceId () );
486503 managedEntity = new ImmutableManagedEntityHolder ( castedEntity );
487- if ( context .immutableManagedEntityXref == null ) {
488- context .immutableManagedEntityXref =
489- new IdentityHashMap <>();
490- }
491- context .immutableManagedEntityXref .put (
492- castedEntity ,
493- (ImmutableManagedEntityHolder ) managedEntity
494-
495- );
504+ context .putImmutableManagedEntity ( castedEntity , (ImmutableManagedEntityHolder ) managedEntity );
496505 }
497506 }
498507 else {
@@ -605,6 +614,15 @@ public ManagedEntityImpl(Object entityInstance) {
605614 public void $$_hibernate_setPreviousManagedEntity (ManagedEntity previous ) {
606615 this .previous = previous ;
607616 }
617+
618+ @ Override
619+ public int $$_hibernate_getInstanceId () {
620+ return -1 ;
621+ }
622+
623+ @ Override
624+ public void $$_hibernate_setInstanceId (int id ) {
625+ }
608626 }
609627
610628 private static class ImmutableManagedEntityHolder implements ManagedEntity {
@@ -693,6 +711,16 @@ private boolean canClearEntityEntryReference() {
693711 return !(entityEntry instanceof ImmutableEntityEntry )
694712 || !entityEntry .getPersister ().canUseReferenceCacheEntries ();
695713 }
714+
715+ @ Override
716+ public int $$_hibernate_getInstanceId () {
717+ return managedEntity .$$_hibernate_getInstanceId ();
718+ }
719+
720+ @ Override
721+ public void $$_hibernate_setInstanceId (int id ) {
722+ managedEntity .$$_hibernate_setInstanceId ( id );
723+ }
696724 }
697725
698726 /**
0 commit comments