@@ -52,7 +52,7 @@ public class EntityEntryContext {
5252 private final transient PersistenceContext persistenceContext ;
5353
5454 private transient InstanceIdentityStore <ImmutableManagedEntityHolder > immutableManagedEntityXref ;
55- private transient int currentInstanceId ;
55+ private transient int currentInstanceId = 1 ;
5656
5757 private transient ManagedEntity head ;
5858 private transient ManagedEntity tail ;
@@ -97,10 +97,13 @@ public void addEntityEntry(Object entity, EntityEntry entityEntry) {
9797 // Throw an exception if entity is a mutable ManagedEntity that is associated with a different
9898 // PersistenceContext.
9999 ManagedEntity managedEntity = getAssociatedManagedEntity ( entity );
100+
101+ int instanceId = nextManagedEntityInstanceId ();
100102 final boolean alreadyAssociated = managedEntity != null ;
101103 if ( !alreadyAssociated ) {
102104 if ( isManagedEntity ( entity ) ) {
103105 final ManagedEntity managed = asManagedEntity ( entity );
106+ assert managed .$$_hibernate_getInstanceId () == 0 ;
104107 if ( entityEntry .getPersister ().isMutable () ) {
105108 managedEntity = managed ;
106109 // We know that managedEntity is not associated with the same PersistenceContext.
@@ -111,11 +114,11 @@ public void addEntityEntry(Object entity, EntityEntry entityEntry) {
111114 // Create a holder for PersistenceContext-related data.
112115 managedEntity = new ImmutableManagedEntityHolder ( managed );
113116 if ( !isReferenceCachingEnabled ( entityEntry .getPersister () ) ) {
114- managed .$$_hibernate_setInstanceId ( nextManagedEntityInstanceId () );
115- putImmutableManagedEntity ( managed , (ImmutableManagedEntityHolder ) managedEntity );
117+ putImmutableManagedEntity ( managed , instanceId , (ImmutableManagedEntityHolder ) managedEntity );
116118 }
117119 else {
118120 // When reference caching is enabled we cannot set the instance-id on the entity instance
121+ instanceId = 0 ;
119122 putManagedEntity ( entity , managedEntity );
120123 }
121124 }
@@ -126,34 +129,33 @@ public void addEntityEntry(Object entity, EntityEntry entityEntry) {
126129 }
127130 }
128131
129- // associate the EntityEntry with the entity
130- managedEntity .$$_hibernate_setEntityEntry ( entityEntry );
131-
132132 if ( alreadyAssociated ) {
133133 // if the entity was already associated with the context, skip the linking step.
134+ managedEntity .$$_hibernate_setEntityEntry ( entityEntry );
134135 return ;
135136 }
136137
137138 // TODO: can dirty be set to true here?
138139
139140 // finally, set up linking and count
141+ final ManagedEntity previous ;
140142 if ( tail == null ) {
141143 assert head == null ;
142- // Protect against stale data in the ManagedEntity and nullify previous/next references.
143- managedEntity .$$_hibernate_setPreviousManagedEntity ( null );
144- managedEntity .$$_hibernate_setNextManagedEntity ( null );
144+ // Protect against stale data in the ManagedEntity and nullify previous reference.
145+ previous = null ;
145146 head = managedEntity ;
146147 tail = head ;
147148 count = 1 ;
148149 }
149150 else {
150151 tail .$$_hibernate_setNextManagedEntity ( managedEntity );
151- managedEntity .$$_hibernate_setPreviousManagedEntity ( tail );
152- // Protect against stale data left in the ManagedEntity nullify next reference.
153- managedEntity .$$_hibernate_setNextManagedEntity ( null );
152+ previous = tail ;
154153 tail = managedEntity ;
155154 count ++;
156155 }
156+
157+ // Protect against stale data left in the ManagedEntity nullify next reference.
158+ managedEntity .$$_hibernate_setPersistenceInfo ( entityEntry , previous , null , instanceId );
157159 }
158160
159161 private static boolean isReferenceCachingEnabled (EntityPersister persister ) {
@@ -201,11 +203,11 @@ private int nextManagedEntityInstanceId() {
201203 return currentInstanceId ++;
202204 }
203205
204- private void putImmutableManagedEntity (ManagedEntity managed , ImmutableManagedEntityHolder holder ) {
206+ private void putImmutableManagedEntity (ManagedEntity managed , int instanceId , ImmutableManagedEntityHolder holder ) {
205207 if ( immutableManagedEntityXref == null ) {
206208 immutableManagedEntityXref = new InstanceIdentityStore <>();
207209 }
208- immutableManagedEntityXref .put ( managed , holder );
210+ immutableManagedEntityXref .put ( managed , instanceId , holder );
209211 }
210212
211213 private void checkNotAssociatedWithOtherPersistenceContextIfMutable (ManagedEntity managedEntity ) {
@@ -288,12 +290,6 @@ else if ( !isManagedEntity( entity ) ) {
288290 nonEnhancedEntityXref .remove ( entity );
289291 }
290292
291- // prepare for re-linking...
292- final ManagedEntity previous = managedEntity .$$_hibernate_getPreviousManagedEntity ();
293- final ManagedEntity next = managedEntity .$$_hibernate_getNextManagedEntity ();
294- managedEntity .$$_hibernate_setPreviousManagedEntity ( null );
295- managedEntity .$$_hibernate_setNextManagedEntity ( null );
296-
297293 // re-link
298294 count --;
299295
@@ -302,11 +298,13 @@ else if ( !isManagedEntity( entity ) ) {
302298 head = null ;
303299 tail = null ;
304300
305- assert previous == null ;
306- assert next == null ;
301+ assert managedEntity . $$_hibernate_getPreviousManagedEntity () == null ;
302+ assert managedEntity . $$_hibernate_getNextManagedEntity () == null ;
307303 }
308304 else {
309305 // otherwise, previous or next (or both) should be non-null
306+ final ManagedEntity previous = managedEntity .$$_hibernate_getPreviousManagedEntity ();
307+ final ManagedEntity next = managedEntity .$$_hibernate_getNextManagedEntity ();
310308 if ( previous == null ) {
311309 // we are removing head
312310 assert managedEntity == head ;
@@ -327,9 +325,7 @@ else if ( !isManagedEntity( entity ) ) {
327325 }
328326
329327 // finally clean out the ManagedEntity and return the associated EntityEntry
330- final EntityEntry theEntityEntry = managedEntity .$$_hibernate_getEntityEntry ();
331- managedEntity .$$_hibernate_setEntityEntry ( null );
332- return theEntityEntry ;
328+ return clearManagedEntity ( managedEntity );
333329 }
334330
335331 /**
@@ -379,7 +375,7 @@ private void clearAllReferencesFromManagedEntities() {
379375 nextManagedEntity = current .$$_hibernate_getNextManagedEntity ();
380376 Object toProcess = current .$$_hibernate_getEntityInstance ();
381377 unsetSession ( asPersistentAttributeInterceptableOrNull ( toProcess ) );
382- clearManagedEntity ( current );//careful this also unlinks from the "next" entry in the list
378+ clearManagedEntity ( current ); //careful this also unlinks from the "next" entry in the list
383379 }
384380 }
385381
@@ -413,13 +409,17 @@ public void clear() {
413409 count = 0 ;
414410
415411 reentrantSafeEntries = null ;
416- currentInstanceId = 0 ;
412+ currentInstanceId = 1 ;
417413 }
418414
419- private static void clearManagedEntity (final ManagedEntity node ) {
420- node .$$_hibernate_setEntityEntry ( null );
421- node .$$_hibernate_setPreviousManagedEntity ( null );
422- node .$$_hibernate_setNextManagedEntity ( null );
415+ /**
416+ * Resets the persistence information in a managed entity, and returns its previous {@link EntityEntry}
417+ *
418+ * @param node the managed entity to clear
419+ * @return the previous {@link EntityEntry} contained in the managed entity
420+ */
421+ private static EntityEntry clearManagedEntity (final ManagedEntity node ) {
422+ return node .$$_hibernate_setPersistenceInfo ( null , null , null , 0 );
423423 }
424424
425425 /**
@@ -503,6 +503,7 @@ public static EntityEntryContext deserialize(ObjectInputStream ois, StatefulPers
503503
504504 final EntityEntry entry = deserializeEntityEntry ( entityEntryClassNameArr , ois , rtn );
505505
506+ final int instanceId = context .nextManagedEntityInstanceId ();
506507 final ManagedEntity managedEntity ;
507508 if ( isEnhanced ) {
508509 final ManagedEntity castedEntity = asManagedEntity ( entity );
@@ -512,8 +513,7 @@ public static EntityEntryContext deserialize(ObjectInputStream ois, StatefulPers
512513 else {
513514 managedEntity = new ImmutableManagedEntityHolder ( castedEntity );
514515 if ( !isReferenceCachingEnabled ( entry .getPersister () ) ) {
515- castedEntity .$$_hibernate_setInstanceId ( context .nextManagedEntityInstanceId () );
516- context .putImmutableManagedEntity ( castedEntity , (ImmutableManagedEntityHolder ) managedEntity );
516+ context .putImmutableManagedEntity ( castedEntity , instanceId , (ImmutableManagedEntityHolder ) managedEntity );
517517 }
518518 else {
519519 context .putManagedEntity ( entity , castedEntity );
@@ -525,16 +525,15 @@ public static EntityEntryContext deserialize(ObjectInputStream ois, StatefulPers
525525 context .putManagedEntity ( entity , managedEntity );
526526 }
527527
528- managedEntity .$$_hibernate_setEntityEntry ( entry );
529-
530528 if ( previous == null ) {
531529 context .head = managedEntity ;
532530 }
533531 else {
534532 previous .$$_hibernate_setNextManagedEntity ( managedEntity );
535- managedEntity .$$_hibernate_setPreviousManagedEntity ( previous );
536533 }
537534
535+ managedEntity .$$_hibernate_setPersistenceInfo ( entry , previous , null , instanceId );
536+
538537 previous = managedEntity ;
539538 }
540539
@@ -631,12 +630,21 @@ public ManagedEntityImpl(Object entityInstance) {
631630
632631 @ Override
633632 public int $$_hibernate_getInstanceId () {
634- return - 1 ;
633+ return 0 ;
635634 }
636635
637636 @ Override
638637 public void $$_hibernate_setInstanceId (int id ) {
639638 }
639+
640+ @ Override
641+ public EntityEntry $$_hibernate_setPersistenceInfo (EntityEntry entityEntry , ManagedEntity previous , ManagedEntity next , int instanceId ) {
642+ final EntityEntry oldEntry = this .entityEntry ;
643+ this .entityEntry = entityEntry ;
644+ this .previous = previous ;
645+ this .next = next ;
646+ return oldEntry ;
647+ }
640648 }
641649
642650 private static class ImmutableManagedEntityHolder implements ManagedEntity {
@@ -662,7 +670,7 @@ public ImmutableManagedEntityHolder(ManagedEntity immutableManagedEntity) {
662670 public void $$_hibernate_setEntityEntry (EntityEntry entityEntry ) {
663671 // need to think about implications for memory leaks here if we don't removed reference to EntityEntry
664672 if ( entityEntry == null ) {
665- if ( canClearEntityEntryReference () ) {
673+ if ( canClearEntityEntryReference ( managedEntity . $$_hibernate_getEntityEntry () ) ) {
666674 managedEntity .$$_hibernate_setEntityEntry ( null );
667675 }
668676 // otherwise, do nothing.
@@ -720,10 +728,9 @@ public ImmutableManagedEntityHolder(ManagedEntity immutableManagedEntity) {
720728
721729 // Check instance type of EntityEntry and if type is ImmutableEntityEntry,
722730 // check to see if entity is referenced cached in the second level cache
723- private boolean canClearEntityEntryReference () {
724- EntityEntry entityEntry = managedEntity .$$_hibernate_getEntityEntry ();
731+ private static boolean canClearEntityEntryReference (EntityEntry entityEntry ) {
725732 return !(entityEntry instanceof ImmutableEntityEntry )
726- || !entityEntry .getPersister (). canUseReferenceCacheEntries ( );
733+ || !isReferenceCachingEnabled ( entityEntry .getPersister () );
727734 }
728735
729736 @ Override
@@ -735,6 +742,25 @@ private boolean canClearEntityEntryReference() {
735742 public void $$_hibernate_setInstanceId (int id ) {
736743 managedEntity .$$_hibernate_setInstanceId ( id );
737744 }
745+
746+ @ Override
747+ public EntityEntry $$_hibernate_setPersistenceInfo (EntityEntry entityEntry , ManagedEntity previous , ManagedEntity next , int instanceId ) {
748+ final EntityEntry oldEntry ;
749+ if ( entityEntry == null ) {
750+ oldEntry = managedEntity .$$_hibernate_getEntityEntry ();
751+ if ( canClearEntityEntryReference ( oldEntry ) ) {
752+ managedEntity .$$_hibernate_setEntityEntry ( null );
753+ }
754+ }
755+ else {
756+ managedEntity .$$_hibernate_setEntityEntry ( entityEntry );
757+ oldEntry = null ; // no need to retrieve the previous entity entry
758+ }
759+ this .previous = previous ;
760+ this .next = next ;
761+ managedEntity .$$_hibernate_setInstanceId ( instanceId );
762+ return oldEntry ;
763+ }
738764 }
739765
740766 /**
0 commit comments