Reputation: 50117
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?
Upvotes: 2
Views: 4878
Reputation: 376
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.
Upvotes: 7