StateManager savedImage retains references - not the original values
Hi,
I've been trying to work with the StateManager and its savedImage object which I had expected to be a representation of the current object at the time that "saveFields()" is called. Unfortunately, I just noticed that this is not the case for any Array / Collection elements. That is to say, that the array object is copied from the source Persistable to the savedImage, but as a shallow-copy only; the savedImage retains the same Collection/Array object as the source. Which means that any changes to the source Collection will be reflected in the savedImage's collection as well. To be more clear, here is some sample objects I'm working with: Persistable:
Eric |
|
1. Talk to developers of TJDO, they wrote basic StateManager handling before DataNucleus existed.
2. If it kept a deep copy then you'd get an object graph stored alongside each object. A StateManager needs to be minimal in storage, or you slow things down. You have seen the code so can see there is no way to "override" it with current codebase, without contributions. 3. No idea. When a SCO collection/map (not an array, since an array is not a type) field is accessed a user is returned the wrapper / proxy, which will be one of these for RDBMS, and one of these for non-RDBMS. It is enabled otherwise DataNucleus would never catch updates to the collection/map. |
|
ebenzacar@...
I found the set of Proxy collections in the `org.datanucleus.store.types.wrappers`. I don't see any state trackers in the SCO proxies that would retain the original values before they are modified. Does anything like this exist in some other format? Eric |
|
It knows what to update based on what methods the user calls on the collection/map. Take the example of a field of type Collection, using
https://github.com/datanucleus/datanucleus-core/blob/master/src/main/java/org/datanucleus/store/types/wrappers/backed/Collection.java The user does an "add" of an element, so calls https://github.com/datanucleus/datanucleus-core/blob/master/src/main/java/org/datanucleus/store/types/wrappers/backed/Collection.java#L645 If using optimistic txns (i.e delaying sending updates to the DB til required) it is a "queued update", so it calls ownerSM.getExecutionContext().addOperationToQueue(new CollectionAddOperation(ownerSM, backingStore, element)); and otherwise (sending updates to the DB immediately) it calls backingStore.add(ownerSM, element, useCache ? delegate.size() : -1); But then that is the whole point of using a proxy, it intercepts calls, and takes action as required. Current use-cases here are for persistence, and since it has all info that it needs for that no "original values" are explicitly stored there. Your use-case is different to what it is designed to cater for |
|