Hi Joachim, I think you are over-complicating things.
1) In Cayenne Modeler, select an ObjEntity (the Java class) and under the Entity tab, turn Optimistic Locking on. Then under the Attributes tab, turn Used for Locking on for each attribute you wish to lock on (you can do the same for Relationships if you desire). That's it. You don't have to track which rows were loaded or modified (Cayenne knows that). When you commitChanges(), it'll do the UPDATE statement as you were suggesting (including the original values -- the ones you Used for Locking -- as part of the UPDATE). If something else has modified the data between the time you read it and committed it, then Cayenne throws an OptimisticLockingException during commitChanges(). mrg On Tue, Feb 21, 2012 at 11:51 AM, Durchholz, Joachim <[email protected]> wrote: >> The short answer is it really depends on your application/requirements. >> For my personal preference, I like to lock on all meaningful columns >> with the exception of blobs unless there is a compelling data/business >> requirement to not do so. You also need to be careful of triggers that >> update things behind the scenes, too. If you have a trigger that updates >> a last-modified column, you wouldn't want to optimistically lock on that >> column because the trigger is going to be changing the value behind your >> back. > > So my understanding is that Cayenne leaves it to the application to > implement optimistic locking. > > I'm not sure how to do that well with Cayenne. My approach would be: > 1) lock all relevant rows > 2) load the relevant rows as Cayenne entities > 3) compare for differences with the unmodified state > 4) if all goes well, trigger Cayenne's commit. > > (1) means I need to know all rows that might be affected. Cayenne tells me > about entities; does it tell me about the rows associated with them? In > the presence of flattened relationships, too? > > (2) means opening another Cayenne context and loading the data I guess. > That should work out of the box. > > (3) means a deep traversal of object networks, while avoiding triggering a > lazy load. > Not sure which parts of the Cayenne API to inspect for that. > Also, not sure how to get that done without writing lots of boilerplate > code. > > (4) should work out of the box. > > So steps (1) and (3) are the ones I don't know how to do. > > ------------- > > There's an approach that halves the number of server roundtrips: Use > UPDATE table SET field = :value > WHERE pk = :id > AND field = :old_value > and check whether that returns an update count of 1 - if field got changed > by another process in the time between local read and update, the UPDATE > will find no record that matches the criteria, do nothing, and return a 0. > > Is there a way to do that in Cayenne? > > (This technique is the one that the Hibernate folks use for their > implementation of optimistic locking.)
