You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@cayenne.apache.org by Juan Manuel Diaz Lara <jm...@yahoo.com.INVALID> on 2016/04/29 00:52:18 UTC

How does optimistic locking works ?

I have this simplified scenario where the second commitChanges fails with an optimistic exception:

        s = CayenneDao.instance.getByPrimaryKey(StockCurrent.class, testStockcurrentId);
        s.setUnits(s.getUnits()+1));
        context.commitChanges();               
        s.setUnits(s.getUnits()+ 7); 
        context.commitChanges();
 I have traced the log and I can see that the version field con s is not updated after first commit, that is annoying because it break's the second commit. 

So the question is: what is the cayenne contract in relation to optimistic locking ? what does it do ? only testing when committing ? does not update version field nor refresh it from db when commiting ?
In my db, I have a version field in every table (integer), and a trigger that updates it if not done from the app, any way, how can I make this to work ? 


Atte. Juan Manuel Díaz Lara

Re: How does optimistic locking works ?

Posted by Michael Gentry <bl...@gmail.com>.
Hi Juan,

I still would suggest getting rid of the version field and optimistically
lock on real data.  If someone/something updates (from an SQL prompt,
editor, external process, etc) the units in StockCurrent's table, but
forgets to increment the version field (which is likely if a human is
making the update), then you will overwrite the new units value because you
are only checking to see if the version field has changed, which it
hasn't.  I don't think the version field provides much value and can lead
to hard-to-locate errors.

mrg


On Fri, Apr 29, 2016 at 4:25 PM, Juan Manuel Diaz Lara <
jmdiazlr@yahoo.com.invalid> wrote:

> Thanks for your reply.... to clarify, my version field is marked as the
> only field used for optimistic locking, and the entity was market too for
> optimistic locking, the problem was that I was expecting cayenne to manage
> the version field, but the only thing it does is to add the condition to
> the where clause to implement the verification part of the optimistic
> locking strategy.
> As I wrote in a previous mail, the solution is to increment the version
> field ourself (from the app code) just before we commit, and for this there
> could be several strategies.
>  Atte. Juan Manuel Díaz Lara
>
>     On Friday, April 29, 2016 8:48 AM, Michael Gentry <bl...@gmail.com>
> wrote:
>
>
>  Hi Juan,
>
> Typically in Cayenne you wouldn't have a version field.  You'd instead
> optimistically lock on "units" and other values.
>
> Assuming you optimistically locked on "units" and using the example code
> you gave, you would only get an exception if some other activity changed
> the value of "units" in the database:
>
> a) after your initial fetch and before your first commitChanges
> b) after your first commitChanges and before your second commitChanges
>
> If you aren't familiar with optimistic locking, in Cayenne Modeler make
> sure you have "Optimistic Locking" checked on your StockCurrent ObjEntity
> (under the "Entity" tab), then also make sure you have "Used for Locking"
> checked (under the "Attributes" tab) for "user" and other attributes.
>
> Cayenne will then verify those checked attributes have not changed when you
> do a commitChanges.  You don't need the version field unless you have a
> requirement to know how many times something has been updated, but that's
> not a very good requirement since you probably really want to know what has
> changed instead, which is an entirely different discussion.
>
> mrg
>
>
> On Thu, Apr 28, 2016 at 10:31 PM, Juan Manuel Diaz Lara <
> jmdiazlr@yahoo.com.invalid> wrote:
>
> > Ok, I was thinking on other frameworks... the simple solution is to
> > increment the version field from the app before commitChanges() (anyway
> the
> > commit will only succeed if the orinal value of the version field is
> equal
> > in the db). I made this on a preUpdate lifecycle event to not forget to
> do
> > it and ensure a monotonically increment.
> > To anyone maybe interested.
> >  Atte. Juan Manuel Díaz Lara
> >
> >    On Thursday, April 28, 2016 5:52 PM, Juan Manuel Diaz Lara
> > <jm...@yahoo.com.INVALID> wrote:
> >
> >
> >  I have this simplified scenario where the second commitChanges fails
> with
> > an optimistic exception:
> >
> >        s = CayenneDao.instance.getByPrimaryKey(StockCurrent.class,
> > testStockcurrentId);
> >        s.setUnits(s.getUnits()+1));
> >        context.commitChanges();
> >        s.setUnits(s.getUnits()+ 7);
> >        context.commitChanges();
> >  I have traced the log and I can see that the version field con s is not
> > updated after first commit, that is annoying because it break's the
> second
> > commit.
> >
> > So the question is: what is the cayenne contract in relation to
> optimistic
> > locking ? what does it do ? only testing when committing ? does not
> update
> > version field nor refresh it from db when commiting ?
> > In my db, I have a version field in every table (integer), and a trigger
> > that updates it if not done from the app, any way, how can I make this to
> > work ?
> >
> >
> > Atte. Juan Manuel Díaz Lara
> >
> >
> >
>
>
>

Re: How does optimistic locking works ?

Posted by Juan Manuel Diaz Lara <jm...@yahoo.com.INVALID>.
Thanks for your reply.... to clarify, my version field is marked as the only field used for optimistic locking, and the entity was market too for optimistic locking, the problem was that I was expecting cayenne to manage the version field, but the only thing it does is to add the condition to the where clause to implement the verification part of the optimistic locking strategy.
As I wrote in a previous mail, the solution is to increment the version field ourself (from the app code) just before we commit, and for this there could be several strategies.
 Atte. Juan Manuel Díaz Lara 

    On Friday, April 29, 2016 8:48 AM, Michael Gentry <bl...@gmail.com> wrote:
 

 Hi Juan,

Typically in Cayenne you wouldn't have a version field.  You'd instead
optimistically lock on "units" and other values.

Assuming you optimistically locked on "units" and using the example code
you gave, you would only get an exception if some other activity changed
the value of "units" in the database:

a) after your initial fetch and before your first commitChanges
b) after your first commitChanges and before your second commitChanges

If you aren't familiar with optimistic locking, in Cayenne Modeler make
sure you have "Optimistic Locking" checked on your StockCurrent ObjEntity
(under the "Entity" tab), then also make sure you have "Used for Locking"
checked (under the "Attributes" tab) for "user" and other attributes.

Cayenne will then verify those checked attributes have not changed when you
do a commitChanges.  You don't need the version field unless you have a
requirement to know how many times something has been updated, but that's
not a very good requirement since you probably really want to know what has
changed instead, which is an entirely different discussion.

mrg


On Thu, Apr 28, 2016 at 10:31 PM, Juan Manuel Diaz Lara <
jmdiazlr@yahoo.com.invalid> wrote:

> Ok, I was thinking on other frameworks... the simple solution is to
> increment the version field from the app before commitChanges() (anyway the
> commit will only succeed if the orinal value of the version field is equal
> in the db). I made this on a preUpdate lifecycle event to not forget to do
> it and ensure a monotonically increment.
> To anyone maybe interested.
>  Atte. Juan Manuel Díaz Lara
>
>    On Thursday, April 28, 2016 5:52 PM, Juan Manuel Diaz Lara
> <jm...@yahoo.com.INVALID> wrote:
>
>
>  I have this simplified scenario where the second commitChanges fails with
> an optimistic exception:
>
>        s = CayenneDao.instance.getByPrimaryKey(StockCurrent.class,
> testStockcurrentId);
>        s.setUnits(s.getUnits()+1));
>        context.commitChanges();
>        s.setUnits(s.getUnits()+ 7);
>        context.commitChanges();
>  I have traced the log and I can see that the version field con s is not
> updated after first commit, that is annoying because it break's the second
> commit.
>
> So the question is: what is the cayenne contract in relation to optimistic
> locking ? what does it do ? only testing when committing ? does not update
> version field nor refresh it from db when commiting ?
> In my db, I have a version field in every table (integer), and a trigger
> that updates it if not done from the app, any way, how can I make this to
> work ?
>
>
> Atte. Juan Manuel Díaz Lara
>
>
>

  

Re: How does optimistic locking works ?

Posted by Michael Gentry <bl...@gmail.com>.
Hi Juan,

Typically in Cayenne you wouldn't have a version field.  You'd instead
optimistically lock on "units" and other values.

Assuming you optimistically locked on "units" and using the example code
you gave, you would only get an exception if some other activity changed
the value of "units" in the database:

a) after your initial fetch and before your first commitChanges
b) after your first commitChanges and before your second commitChanges

If you aren't familiar with optimistic locking, in Cayenne Modeler make
sure you have "Optimistic Locking" checked on your StockCurrent ObjEntity
(under the "Entity" tab), then also make sure you have "Used for Locking"
checked (under the "Attributes" tab) for "user" and other attributes.

Cayenne will then verify those checked attributes have not changed when you
do a commitChanges.  You don't need the version field unless you have a
requirement to know how many times something has been updated, but that's
not a very good requirement since you probably really want to know what has
changed instead, which is an entirely different discussion.

mrg


On Thu, Apr 28, 2016 at 10:31 PM, Juan Manuel Diaz Lara <
jmdiazlr@yahoo.com.invalid> wrote:

> Ok, I was thinking on other frameworks... the simple solution is to
> increment the version field from the app before commitChanges() (anyway the
> commit will only succeed if the orinal value of the version field is equal
> in the db). I made this on a preUpdate lifecycle event to not forget to do
> it and ensure a monotonically increment.
> To anyone maybe interested.
>  Atte. Juan Manuel Díaz Lara
>
>     On Thursday, April 28, 2016 5:52 PM, Juan Manuel Diaz Lara
> <jm...@yahoo.com.INVALID> wrote:
>
>
>  I have this simplified scenario where the second commitChanges fails with
> an optimistic exception:
>
>         s = CayenneDao.instance.getByPrimaryKey(StockCurrent.class,
> testStockcurrentId);
>         s.setUnits(s.getUnits()+1));
>         context.commitChanges();
>         s.setUnits(s.getUnits()+ 7);
>         context.commitChanges();
>  I have traced the log and I can see that the version field con s is not
> updated after first commit, that is annoying because it break's the second
> commit.
>
> So the question is: what is the cayenne contract in relation to optimistic
> locking ? what does it do ? only testing when committing ? does not update
> version field nor refresh it from db when commiting ?
> In my db, I have a version field in every table (integer), and a trigger
> that updates it if not done from the app, any way, how can I make this to
> work ?
>
>
> Atte. Juan Manuel Díaz Lara
>
>
>

Re: How does optimistic locking works ?

Posted by Juan Manuel Diaz Lara <jm...@yahoo.com.INVALID>.
Ok, I was thinking on other frameworks... the simple solution is to increment the version field from the app before commitChanges() (anyway the commit will only succeed if the orinal value of the version field is equal in the db). I made this on a preUpdate lifecycle event to not forget to do it and ensure a monotonically increment.
To anyone maybe interested.
 Atte. Juan Manuel Díaz Lara 

    On Thursday, April 28, 2016 5:52 PM, Juan Manuel Diaz Lara <jm...@yahoo.com.INVALID> wrote:
 

 I have this simplified scenario where the second commitChanges fails with an optimistic exception:

        s = CayenneDao.instance.getByPrimaryKey(StockCurrent.class, testStockcurrentId);
        s.setUnits(s.getUnits()+1));
        context.commitChanges();               
        s.setUnits(s.getUnits()+ 7); 
        context.commitChanges();
 I have traced the log and I can see that the version field con s is not updated after first commit, that is annoying because it break's the second commit. 

So the question is: what is the cayenne contract in relation to optimistic locking ? what does it do ? only testing when committing ? does not update version field nor refresh it from db when commiting ?
In my db, I have a version field in every table (integer), and a trigger that updates it if not done from the app, any way, how can I make this to work ? 


Atte. Juan Manuel Díaz Lara