`

From: Sean Tan (sabrebox2000-cod..ahoo.com.sg)
Date: Fri Aug 26 2005 - 11:17:01 EDT

  • Next message: Sean Tan: "Re: PersistenceState relation to property changes"

    Thanks alot for pointing that out Mike! I missed out the problem.

    I have taken your suggestion and Andrus to implement my solution.

    I have included the code here for completeness sake of the discussion.
    -----
    public class MyCayenneDataObject extends
    org.objectstyle.cayenne.CayenneDataObject {

        public void writeProperty(String propName, Object val) {
            resolveFault();

            // 1. retain object snapshot to allow clean changes tracking
            // 2. change object state
            if (persistenceState == PersistenceState.COMMITTED) {
                DataRow committedSnapshot =
    dataContext.getObjectStore().getCachedSnapshot(getObjectId());
                boolean modified = false;
                if (committedSnapshot == null) {
                    modified = true;
                } else {
                    Object oldValue = committedSnapshot.get(propName);
                    modified = !Util.nullSafeEquals(oldValue, val);
                }
                if (modified) {
                    persistenceState = PersistenceState.MODIFIED;
                    dataContext.getObjectStore().retainSnapshot(this);
                }
            }
            // else....
            // other persistence states can't be changed to MODIFIED

            writePropertyDirectly(propName, val);
        }

    }
    -----
        protected void validateForSave(ValidationResult validationResult) {
            setTimestamp(new Date(System.currentTimeMillis()));
            super.validateForSave(validationResult);
        }
     -----

    Sean

    Mike Kienenberger wrote:

    >The problem with doing it with writeProperty() is that it won't detect
    >differences in this situation:
    >
    >obj.getField() == 1
    >
    >obj.setField(0);
    >obj.setField(1);
    >obj.getDataContext().commit;
    >
    >However, as Andrus states, if you want to do this, it's trivial to
    >handle this in a base DataObject superclass.
    >
    >(In fact, I override writeObject in a base DataObject superclass to
    >change empty strings to null since Oracle doesn't handle empty
    >strings.
    >
    >If you're willing to dig into the advanced parts of Cayenne a little
    >more, you can use the same logic that Cayenne uses for determining
    >which objects have changed fields in validate*.
    >
    >You'd just compare the current value snapshots with the original
    >object snapshots.
    >
    >On 8/26/05, Sean Tan <sabrebox2000-cod..ahoo.com.sg> wrote:
    >
    >
    >>Thanks a lot for very quick reply Andrus! =)
    >>Hmm.... I tried your suggestion but notice the follow things:
    >>1. Cayenne relies on DataContext.hasChanges() to know whether there is
    >>any real modifications. But this only allows Cayenne to know whether
    >>there are any modifications within the DataContext, not based on
    >>individual DataObjects.
    >>2. Due to the above, once there is a single modified DataObject within
    >>the DataContext, the validate* methods will be called for all
    >>DataObjects marked modified.
    >>
    >>As such, I think your suggestion does not work.
    >>
    >>I'm not sure how useful will it be to the rest of the users, but I guess
    >>having the PersistenceState.MODIFIED to reflect real modifications are
    >>intuitive and useful in most cases. Or perhaps we can have an option to
    >>turn it On/Off....
    >>
    >>On the same line, perhaps out-of-the-box Cayenne could support the use
    >>of fields like TimeStamp, as it would help alot in users who are
    >>re-engineering from existing DB systems which relies on this feature.
    >>
    >>--
    >>Sean
    >>
    >>Andrus Adamchik wrote:
    >>
    >>
    >>
    >>>Hi there,
    >>>
    >>>Your solution will work and you can put your overridden
    >>>"writeProperty" in your own custom superclass of DataObjects thus
    >>>changing default Cayenne behavior.
    >>>
    >>>Here is another solution however - override "validateForSave" to add
    >>>your timestamp logic:
    >>>
    >>>http://objectstyle.org/cayenne/userguide/dataobjects/validation.html
    >>>
    >>>See, even if an object is marked as modified on "setXYZ" call when
    >>>there was no real modification, this fact will be detected by Cayenne
    >>>later on commit, and the object will not be committed, and its
    >>>validate* methods won't be called.
    >>>
    >>>Hope this helps.
    >>>
    >>>Andrus
    >>>
    >>>On Aug 26, 2005, at 2:03 PM, Sean Tan wrote:
    >>>
    >>>
    >>>
    >>>>I'm attempting to use Cayenne v1.1.2 with the idea of having a field
    >>>>that mimics the behavior of MySql's TimeStamp dbtype.
    >>>>
    >>>>The timestamp will only update if at least a change is detected in the
    >>>>rest of the columns.
    >>>>
    >>>>I'm trying to rely on the PersistenceState of CayenneDataObject but I
    >>>>realized that the PersistenceState is set to Modified even when the new
    >>>>value being introduced is the same as the old value. This poses a
    >>>>problem, especially in the context of webframeworks like Tapestry which
    >>>>all bounded fields will be updated, meaning the writeProperty(String
    >>>>propName, Object val) of the CayenneDataObject will always be
    >>>>called....
    >>>>PersistenceState being set to Modified although no change is made.
    >>>>
    >>>>One usage scenario is when you create a HTML table of records which
    >>>>allows the user to change the records inline, and click on a update
    >>>>button.
    >>>>
    >>>>Thus, I'm proposing that perhaps the writeProperty method could be
    >>>>adjusted to do additional check as below to suit this purpose.
    >>>>----
    >>>>public void writeProperty(String propName, Object val) {
    >>>> resolveFault();
    >>>>
    >>>> // 1. retain object snapshot to allow clean changes tracking
    >>>> // 2. change object state
    >>>> Object oldVal = readPropertyDirectly(propName);
    >>>> if (persistenceState == PersistenceState.COMMITTED &&
    >>>>oldVal.equals(val) == false) {
    >>>> persistenceState = PersistenceState.MODIFIED;
    >>>> dataContext.getObjectStore().retainSnapshot(this);
    >>>> }
    >>>> // else....
    >>>> // other persistence states can't be changed to MODIFIED
    >>>>
    >>>> writePropertyDirectly(propName, val);
    >>>> }
    >>>>-----
    >>>>
    >>>>Or am I missing out a better way to do this?
    >>>>
    >>>>--
    >>>>Sean Tan
    >>>>
    >>>>
    >>>
    >>>
    >>>
    >>Send instant messages to your online friends http://asia.messenger.yahoo.com
    >>
    >>
    >>
    >>
    >
    >
    >
    Send instant messages to your online friends http://asia.messenger.yahoo.com



    This archive was generated by hypermail 2.0.0 : Fri Aug 26 2005 - 11:18:05 EDT