Details
-
Type:
Sub-task
-
Status:
Closed
-
Priority:
Minor
-
Resolution: Fixed
-
Affects Version/s: 1.0.2
-
Fix Version/s: 1.1-beta1
-
Component/s: Persistence
-
Labels:None
-
Environment:OSX + Postgres
-
Testcase included:yes
Description
Grails Pesismistic Locking doesn't work.
- domainObject.lock() has no effect
- DomainObject.lock(id) doesn't take longs or Integers
I've uploaded a test project that demonstrates this. The project uses Postgres and the drives the application through HttpUnit. You'll need to create a db called lockbug to reproduce (or edit DataSource.groovy)
It appears the only way to actually lock objects in grails is to jump through some hibernate hoops or use a SQL statement (as follows).
import org.hibernate.SessionFactory
import org.hibernate.LockMode
class AccountService {
SessionFactory sessionFactory
int incrementWithDynamicLockMethod(String name) {
Account account = Account.findByName(name)
account.lock() // Doesn't lock
account.balance++
account.save(flush:true)
return account.balance
}
int incrementWithStaticLockMethod(String name) {
Account account = Account.findByName(name)
account = Account.lock(account.id) // Throws exception (doesn't take Longs or Strings)
account.balance++
account.save(flush:true)
return account.balance
}
int incrementWithHibernateLockMethod(String name) {
Account account = Account.findByName(name)
sessionFactory.currentSession.lock(account, LockMode.UPGRADE) // Does nothing because account already in the session
account.balance++
account.save(flush:true)
return account.balance
}
int incrementWithHibernateLoadMethod(String name) {
Account account = Account.findByName(name)
sessionFactory.currentSession.clear() // Need to clear the session to force db load (may be able to use evict in some circumstances)
account = sessionFactory.currentSession.load(Account.class, account.id, LockMode.UPGRADE)
account.balance++
account.save(flush:true)
return account.balance
}
int incrementWithPostgresLockStatement(String name) {
sessionFactory.currentSession.createSQLQuery('LOCK account IN ACCESS EXCLUSIVE MODE').executeUpdate() // Full Table Lock just for example
Account account = Account.findByName(name)
account.balance++
account.save(flush:true)
return account.balance
}
}
Issue Links
- depends on
-
GRAILS-3402
Add lock:true parameter for queries and criteria
-
Slight correction,