@@ -52,7 +52,7 @@ public class EntityEntryContext {
52
52
private final transient PersistenceContext persistenceContext ;
53
53
54
54
private transient InstanceIdentityStore <ImmutableManagedEntityHolder > immutableManagedEntityXref ;
55
- private transient int currentInstanceId ;
55
+ private transient int currentInstanceId = 1 ;
56
56
57
57
private transient ManagedEntity head ;
58
58
private transient ManagedEntity tail ;
@@ -97,10 +97,13 @@ public void addEntityEntry(Object entity, EntityEntry entityEntry) {
97
97
// Throw an exception if entity is a mutable ManagedEntity that is associated with a different
98
98
// PersistenceContext.
99
99
ManagedEntity managedEntity = getAssociatedManagedEntity ( entity );
100
+
101
+ int instanceId = nextManagedEntityInstanceId ();
100
102
final boolean alreadyAssociated = managedEntity != null ;
101
103
if ( !alreadyAssociated ) {
102
104
if ( isManagedEntity ( entity ) ) {
103
105
final ManagedEntity managed = asManagedEntity ( entity );
106
+ assert managed .$$_hibernate_getInstanceId () == 0 ;
104
107
if ( entityEntry .getPersister ().isMutable () ) {
105
108
managedEntity = managed ;
106
109
// We know that managedEntity is not associated with the same PersistenceContext.
@@ -111,11 +114,11 @@ public void addEntityEntry(Object entity, EntityEntry entityEntry) {
111
114
// Create a holder for PersistenceContext-related data.
112
115
managedEntity = new ImmutableManagedEntityHolder ( managed );
113
116
if ( !isReferenceCachingEnabled ( entityEntry .getPersister () ) ) {
114
- managed .$$_hibernate_setInstanceId ( nextManagedEntityInstanceId () );
115
- putImmutableManagedEntity ( managed , (ImmutableManagedEntityHolder ) managedEntity );
117
+ putImmutableManagedEntity ( managed , instanceId , (ImmutableManagedEntityHolder ) managedEntity );
116
118
}
117
119
else {
118
120
// When reference caching is enabled we cannot set the instance-id on the entity instance
121
+ instanceId = 0 ;
119
122
putManagedEntity ( entity , managedEntity );
120
123
}
121
124
}
@@ -126,34 +129,33 @@ public void addEntityEntry(Object entity, EntityEntry entityEntry) {
126
129
}
127
130
}
128
131
129
- // associate the EntityEntry with the entity
130
- managedEntity .$$_hibernate_setEntityEntry ( entityEntry );
131
-
132
132
if ( alreadyAssociated ) {
133
133
// if the entity was already associated with the context, skip the linking step.
134
+ managedEntity .$$_hibernate_setEntityEntry ( entityEntry );
134
135
return ;
135
136
}
136
137
137
138
// TODO: can dirty be set to true here?
138
139
139
140
// finally, set up linking and count
141
+ final ManagedEntity previous ;
140
142
if ( tail == null ) {
141
143
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 ;
145
146
head = managedEntity ;
146
147
tail = head ;
147
148
count = 1 ;
148
149
}
149
150
else {
150
151
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 ;
154
153
tail = managedEntity ;
155
154
count ++;
156
155
}
156
+
157
+ // Protect against stale data left in the ManagedEntity nullify next reference.
158
+ managedEntity .$$_hibernate_setPersistenceInfo ( entityEntry , previous , null , instanceId );
157
159
}
158
160
159
161
private static boolean isReferenceCachingEnabled (EntityPersister persister ) {
@@ -201,11 +203,11 @@ private int nextManagedEntityInstanceId() {
201
203
return currentInstanceId ++;
202
204
}
203
205
204
- private void putImmutableManagedEntity (ManagedEntity managed , ImmutableManagedEntityHolder holder ) {
206
+ private void putImmutableManagedEntity (ManagedEntity managed , int instanceId , ImmutableManagedEntityHolder holder ) {
205
207
if ( immutableManagedEntityXref == null ) {
206
208
immutableManagedEntityXref = new InstanceIdentityStore <>();
207
209
}
208
- immutableManagedEntityXref .put ( managed , holder );
210
+ immutableManagedEntityXref .put ( managed , instanceId , holder );
209
211
}
210
212
211
213
private void checkNotAssociatedWithOtherPersistenceContextIfMutable (ManagedEntity managedEntity ) {
@@ -288,12 +290,6 @@ else if ( !isManagedEntity( entity ) ) {
288
290
nonEnhancedEntityXref .remove ( entity );
289
291
}
290
292
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
-
297
293
// re-link
298
294
count --;
299
295
@@ -302,11 +298,13 @@ else if ( !isManagedEntity( entity ) ) {
302
298
head = null ;
303
299
tail = null ;
304
300
305
- assert previous == null ;
306
- assert next == null ;
301
+ assert managedEntity . $$_hibernate_getPreviousManagedEntity () == null ;
302
+ assert managedEntity . $$_hibernate_getNextManagedEntity () == null ;
307
303
}
308
304
else {
309
305
// otherwise, previous or next (or both) should be non-null
306
+ final ManagedEntity previous = managedEntity .$$_hibernate_getPreviousManagedEntity ();
307
+ final ManagedEntity next = managedEntity .$$_hibernate_getNextManagedEntity ();
310
308
if ( previous == null ) {
311
309
// we are removing head
312
310
assert managedEntity == head ;
@@ -327,9 +325,7 @@ else if ( !isManagedEntity( entity ) ) {
327
325
}
328
326
329
327
// 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 );
333
329
}
334
330
335
331
/**
@@ -379,7 +375,7 @@ private void clearAllReferencesFromManagedEntities() {
379
375
nextManagedEntity = current .$$_hibernate_getNextManagedEntity ();
380
376
Object toProcess = current .$$_hibernate_getEntityInstance ();
381
377
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
383
379
}
384
380
}
385
381
@@ -413,13 +409,17 @@ public void clear() {
413
409
count = 0 ;
414
410
415
411
reentrantSafeEntries = null ;
416
- currentInstanceId = 0 ;
412
+ currentInstanceId = 1 ;
417
413
}
418
414
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 );
423
423
}
424
424
425
425
/**
@@ -503,6 +503,7 @@ public static EntityEntryContext deserialize(ObjectInputStream ois, StatefulPers
503
503
504
504
final EntityEntry entry = deserializeEntityEntry ( entityEntryClassNameArr , ois , rtn );
505
505
506
+ final int instanceId = context .nextManagedEntityInstanceId ();
506
507
final ManagedEntity managedEntity ;
507
508
if ( isEnhanced ) {
508
509
final ManagedEntity castedEntity = asManagedEntity ( entity );
@@ -512,8 +513,7 @@ public static EntityEntryContext deserialize(ObjectInputStream ois, StatefulPers
512
513
else {
513
514
managedEntity = new ImmutableManagedEntityHolder ( castedEntity );
514
515
if ( !isReferenceCachingEnabled ( entry .getPersister () ) ) {
515
- castedEntity .$$_hibernate_setInstanceId ( context .nextManagedEntityInstanceId () );
516
- context .putImmutableManagedEntity ( castedEntity , (ImmutableManagedEntityHolder ) managedEntity );
516
+ context .putImmutableManagedEntity ( castedEntity , instanceId , (ImmutableManagedEntityHolder ) managedEntity );
517
517
}
518
518
else {
519
519
context .putManagedEntity ( entity , castedEntity );
@@ -525,16 +525,15 @@ public static EntityEntryContext deserialize(ObjectInputStream ois, StatefulPers
525
525
context .putManagedEntity ( entity , managedEntity );
526
526
}
527
527
528
- managedEntity .$$_hibernate_setEntityEntry ( entry );
529
-
530
528
if ( previous == null ) {
531
529
context .head = managedEntity ;
532
530
}
533
531
else {
534
532
previous .$$_hibernate_setNextManagedEntity ( managedEntity );
535
- managedEntity .$$_hibernate_setPreviousManagedEntity ( previous );
536
533
}
537
534
535
+ managedEntity .$$_hibernate_setPersistenceInfo ( entry , previous , null , instanceId );
536
+
538
537
previous = managedEntity ;
539
538
}
540
539
@@ -631,12 +630,21 @@ public ManagedEntityImpl(Object entityInstance) {
631
630
632
631
@ Override
633
632
public int $$_hibernate_getInstanceId () {
634
- return - 1 ;
633
+ return 0 ;
635
634
}
636
635
637
636
@ Override
638
637
public void $$_hibernate_setInstanceId (int id ) {
639
638
}
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
+ }
640
648
}
641
649
642
650
private static class ImmutableManagedEntityHolder implements ManagedEntity {
@@ -662,7 +670,7 @@ public ImmutableManagedEntityHolder(ManagedEntity immutableManagedEntity) {
662
670
public void $$_hibernate_setEntityEntry (EntityEntry entityEntry ) {
663
671
// need to think about implications for memory leaks here if we don't removed reference to EntityEntry
664
672
if ( entityEntry == null ) {
665
- if ( canClearEntityEntryReference () ) {
673
+ if ( canClearEntityEntryReference ( managedEntity . $$_hibernate_getEntityEntry () ) ) {
666
674
managedEntity .$$_hibernate_setEntityEntry ( null );
667
675
}
668
676
// otherwise, do nothing.
@@ -720,10 +728,9 @@ public ImmutableManagedEntityHolder(ManagedEntity immutableManagedEntity) {
720
728
721
729
// Check instance type of EntityEntry and if type is ImmutableEntityEntry,
722
730
// 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 ) {
725
732
return !(entityEntry instanceof ImmutableEntityEntry )
726
- || !entityEntry .getPersister (). canUseReferenceCacheEntries ( );
733
+ || !isReferenceCachingEnabled ( entityEntry .getPersister () );
727
734
}
728
735
729
736
@ Override
@@ -735,6 +742,25 @@ private boolean canClearEntityEntryReference() {
735
742
public void $$_hibernate_setInstanceId (int id ) {
736
743
managedEntity .$$_hibernate_setInstanceId ( id );
737
744
}
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
+ }
738
764
}
739
765
740
766
/**
0 commit comments