Or I suppose you could create fields for each of the original values in the same way that the current values are stored.
On Wed, Sep 12, 2018 at 4:32 PM John Huss <johnth...@gmail.com> wrote: > Cayenne stores the original values, but they are in DbEntity > representation rather than ObjEntity representation which makes comparing > the two difficult. Without writing a lot of code to convert and compare > your best bet would be to use a more efficient data structure without any > extra unneeded space. That would be an array (Object[]) that is smart > enough to map a fixed set of string keys into array indexes. To do this > you'll need a HashMap<String, Integer> per ObjEntity(table) that maps from > string key to array index. Then all of your CayenneDataObjects will need an > Object[] with the original values. > > On Tue, Sep 11, 2018 at 10:58 AM Matt R Watson <m...@swarmbox.com> wrote: > >> Thanks mrg. >> >> I am aware that Cayenne knows about the original values, but trying to >> find an efficient way to access them. Or at least more efficient than the >> Map we are currently using, which is heavy on memory yet quick on access >> time (and easy to read code). I’ve seen your utilities in the past when >> searching for a solution for this, but I don’t see anything thats >> comparable to finding the original value of a specific property on a >> specific object. I also don’t see where you are grabbing the original value >> of a relationship. I know the snapshot can show me the original DataRow >> values, but I don’t think those are always the same “type” as the actual >> DataObject properties. >> >> Still hoping for solution for our current code (that doesn’t have to loop >> over all modified objects, every time): >> >> inventoryAdjustment.isPropertyModified(“date”) >> inventoryAdjustment.getOriginalProperty(“date”) >> >> with something like: >> >> Cayenne.isPropertyModified(inventoryAdjustment, "date”) >> Cayenne.getOriginalProperty(inventoryAdjustment, "date”) >> >> Thanks, >> Matt >> >> > On Sep 11, 2018, at 5:31 AM, Michael Gentry <blackn...@gmail.com> >> wrote: >> > >> > Hi Matt, >> > >> > Cayenne already keeps track of the original values for you. This is >> needed >> > in order to do optimistic locking, plus it allows Cayenne to only send >> over >> > changes in a record instead of the entire record when you are doing an >> > UPDATE. >> > >> > I haven't tried this approach on the field-based version of Cayenne yet, >> > but these two utility methods are similar and illustrate how to find the >> > underlying values and detect the changes, at least in 3.x: >> > >> > >> https://gist.github.com/mrg/4dce22b67175c27f4047#file-cayenneutils-java-L124 >> > >> > >> https://gist.github.com/mrg/4dce22b67175c27f4047#file-cayenneutils-java-L184 >> > >> > I believe you could adapt for your purposes/needs pretty readily. >> > >> > mrg >> > >> > >> > On Mon, Sep 10, 2018 at 8:04 PM Matt R Watson <m...@swarmbox.com> >> wrote: >> > >> >> Now that the DataObject classes are “field based”, I would like to >> find a >> >> way to replace the heavy Map we have placed on all of our DataObject >> >> classes. >> >> >> >> We extend Cayenne’s default class and added a HashMap to keep track of >> the >> >> original values (as it changes) since the object has been loaded and >> before >> >> committing. (see our class below) >> >> >> >> This allows us to check if something is modified ( >> >> inventoryAdjustment.isPropertyModified(“date”), or >> >> inventoryAdjustment.getOriginalProperty(“date”) ) >> >> >> >> I’d like to find a Cayenne friendly way of doing this. Any suggestions? >> >> >> >> Thanks, >> >> Matt >> >> >> >> ---------------------------------------------------- >> >> >> >> >> >> public class CayenneBaseDataObject extends CayenneDataObject { >> >> >> >> /** >> >> * Stores the original values for this object's properties. Uses >> >> the >> >> * property name string as the key for each entry. Its purpose >> is >> >> to keep >> >> * track of any original values since the object was initialized >> >> or last >> >> * committed. >> >> */ >> >> private final Map<String,Object> originalPropertyMap = New.map(); >> >> >> >> /** >> >> * Initializes the originalPropertyMap. Used as a callback >> during >> >> the >> >> */ >> >> public void initializeOriginalPropertyMap() { >> >> originalPropertyMap.clear(); >> >> } >> >> >> >> @Override >> >> protected void beforePropertyWrite(String propName, Object oldValue, >> >> Object newValue) { >> >> if (!originalPropertyMap.containsKey(propName)) { >> >> originalPropertyMap.put(propName, oldValue); >> >> } >> >> >> >> super.beforePropertyWrite(propName, oldValue, newValue); >> >> } >> >> >> >> /** >> >> * Overrides >> >> * {@link org.apache.cayenne.DataObject#writeProperty(String, >> >> Object)} by >> >> * saving a {@link CayenneBaseDataObject}'s existing property >> >> value, if any, >> >> * to the {@link #originalPropertyMap} prior to updating the >> >> * {@link CayenneBaseDataObject}'s property with a new value. >> >> * >> >> * @param relationship >> >> * the name of the to-one-relationship >> >> * @param value >> >> * the value used to set the to-one-relationship >> >> * @param reverse >> >> * a boolean indicating whether to set the reverse >> >> relationship as well >> >> */ >> >> @Override >> >> public void setToOneTarget(final String relationship, final >> >> org.apache.cayenne.DataObject value, final boolean reverse) { >> >> if (!originalPropertyMap.containsKey(relationship)) { >> >> originalPropertyMap.put(relationship, >> >> this.readProperty(relationship)); >> >> } >> >> >> >> super.setToOneTarget(relationship, value, reverse); >> >> } >> >> >> >> >> >> @Override >> >> public Object getOriginalProperty(final String property) { >> >> if (!originalPropertyMap.containsKey(property)) { >> >> return this.readProperty(property); >> >> } >> >> >> >> return originalPropertyMap.get(property); >> >> } >> >> >> >> @Override >> >> public Boolean isPropertyModified(final String property) { >> >> final Object original = >> this.getOriginalProperty(property); >> >> final Object current = this.readProperty(property); >> >> >> >> return !Objects.equals(original, current); >> >> } >> >> >> >> } >> >> >> >> >> >>