views:

649

answers:

1

Let's say I have a counter function which updates a counter using raw SQL:

 public void updateCounter() {
   executeSql("UPDATE counter SET count_value = count_value + 1 WHERE id = 1;");
 }

The database would make sure that two concurrent calls to the counter are handled as expected - that all calls would update the counter with one increment and no updates would get lost.

Rather than executing this by issuing a raw SQL command I'd like to use GORM. The naïve way to do it would be something along the lines of:

 public void updateCounter() {
   Counter c = Counter.get(1)
   c.countValue += 1
   c.save()
 }

In this case I'd assume that an update could be lost if two threads call the updateCounter() method at the same moment. What is the correct "Grails/GORM-way" to handle this concurrency issue?

+4  A: 

You could use either 'pessimistic' or 'optimistic' locking strategies, which both supported by Hibernate and therefore by GORM. The default GORM strategy is 'optimistic' (which utilizes the version column/property of the persistent domain entity, created by default). It could be used like this:

...
try {
 Counter c = Counter.get(1)
 c.countValue += 1
 c.save(flush:true)
}
catch(org.springframework.dao.OptimisticLockingFailureException e) {
// deal with concurrent modification here
}
...

If you prefer the 'pessimistic' locking strategy instead (which will block all other concurrent reads, btw), you could do it using explicit 'lock' GORM meta-method, like so:

...
Counter c = Counter.lock(1) //lock the entire row for update
c.countValue += 1
c.save(flush:true) //GORM will autorelease the lock once the TX is committed
...

Hope this helps.

Dmitriy Kopylenko
what do you mean when you say "deal with concurrent modification here" ?you mean to use a "merge" or what else?Cheers
Mulone