44
44
import org .apache .cayenne .reflect .PropertyVisitor ;
45
45
import org .apache .cayenne .reflect .ToManyProperty ;
46
46
import org .apache .cayenne .reflect .ToOneProperty ;
47
+ import org .apache .cayenne .util .SoftValueMap ;
48
+ import org .apache .cayenne .util .WeakValueMap ;
47
49
48
50
import java .io .Serializable ;
49
51
import java .util .ArrayList ;
53
55
import java .util .Iterator ;
54
56
import java .util .List ;
55
57
import java .util .Map ;
56
- import java .util .Set ;
57
58
import java .util .concurrent .ConcurrentHashMap ;
58
59
59
60
/**
@@ -109,13 +110,23 @@ public class ObjectStore implements Serializable, SnapshotEventListener, GraphMa
109
110
*/
110
111
public ObjectStore (DataRowStore dataRowCache , Map <Object , Persistent > objectMap ) {
111
112
setDataRowCache (dataRowCache );
112
- if (objectMap != null ) {
113
- this .objectMap = objectMap ;
114
- }
115
- else {
113
+ setObjectMap (objectMap );
114
+ this .changes = new HashMap <>();
115
+ }
116
+
117
+ /**
118
+ * @since 4.2.2
119
+ */
120
+ void setObjectMap (Map <Object , Persistent > objectMap ) {
121
+ if (objectMap == null ) {
116
122
throw new CayenneRuntimeException ("Object map is null." );
117
123
}
118
- this .changes = new HashMap <>();
124
+ this .objectMap = objectMap ;
125
+ if (objectMap instanceof SoftValueMap ) {
126
+ ((SoftValueMap <Object , Persistent >) objectMap ).setKeyCleanupCallback (this ::onObjectKeyCleanup );
127
+ } else if (objectMap instanceof WeakValueMap ) {
128
+ ((WeakValueMap <Object , Persistent >) objectMap ).setKeyCleanupCallback (this ::onObjectKeyCleanup );
129
+ }
119
130
}
120
131
121
132
/**
@@ -138,7 +149,7 @@ void childContextSyncStopped() {
138
149
Collection <GraphDiff > getLifecycleEventInducedChanges () {
139
150
return lifecycleEventInducedChanges != null
140
151
? lifecycleEventInducedChanges
141
- : Collections .< GraphDiff > emptyList ();
152
+ : Collections .emptyList ();
142
153
}
143
154
144
155
void registerLifecycleEventInducedChange (GraphDiff diff ) {
@@ -416,6 +427,9 @@ public void postprocessAfterCommit(GraphDiff parentChanges) {
416
427
switch (object .getPersistenceState ()) {
417
428
case PersistenceState .DELETED :
418
429
objectMap .remove (id );
430
+ if (trackedFlattenedPaths != null ) {
431
+ trackedFlattenedPaths .remove (id );
432
+ }
419
433
object .setObjectContext (null );
420
434
object .setPersistenceState (PersistenceState .TRANSIENT );
421
435
break ;
@@ -640,9 +654,11 @@ void processDeletedID(ObjectId nodeId) {
640
654
if (dataObject == null || delegate .shouldProcessDelete (dataObject )) {
641
655
objectMap .remove (nodeId );
642
656
changes .remove (nodeId );
657
+ if (trackedFlattenedPaths != null ) {
658
+ trackedFlattenedPaths .remove (nodeId );
659
+ }
643
660
644
- // setting DataContext to null will also set
645
- // state to transient
661
+ // setting DataContext to null will also set state to transient
646
662
object .setObjectContext (null );
647
663
648
664
if (dataObject != null ) {
@@ -1049,6 +1065,16 @@ public void markFlattenedPath(ObjectId objectId, String path, ObjectId id) {
1049
1065
.put (path , id );
1050
1066
}
1051
1067
1068
+ /**
1069
+ * @param key object id that was removed from the {@link #objectMap}
1070
+ * @since 4.2.2
1071
+ */
1072
+ void onObjectKeyCleanup (Object key ) {
1073
+ if (trackedFlattenedPaths != null ) {
1074
+ trackedFlattenedPaths .remove (key );
1075
+ }
1076
+ }
1077
+
1052
1078
// an ObjectIdQuery optimized for retrieval of multiple snapshots - it can be reset
1053
1079
// with the new id
1054
1080
final class CachedSnapshotQuery extends ObjectIdQuery {
0 commit comments