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:20:20 EDT