Re: PersistenceState relation to property changes

From: Mike Kienenberger (mkienen..mail.com)
Date: Fri Aug 26 2005 - 11:29:23 EDT

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

    If it were me, I'd still add a check in validateForSave() to make sure
    that the current valuees being committed were different from the
    cached snapshot, and I wouldn't try to modify the persistence state in
    writeProperty.

    On 8/26/05, Sean Tan <sabrebox2000-cod..ahoo.com.sg> wrote:
    > 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:29:25 EDT