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);
> >>        }
> >>
> >> }
> >>
> >>
>
>

Reply via email to