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