Reputation: 1
-- Update: It turns out that we can't update any domain object at all. We created very simple domain/service/controller combination and still getting the StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.sra.cgms.test.TestDomain#1] Here is our domain class
class TestDomain {
static mapping = {
table name:'TEST_DOMAIN', schema:'cgms'
id generator:'identity', column:'id', sqlType: 'int'
}
String someVal
static constraints = {
someVal(nullable: true)
}
}
Here is our service class:
class TestService {
public void updateDomain(int domainId) {
TestDomain testDomain = TestDomain.get(1)
testDomain.someVal = "updated Val"
testDomain.save(flush: true, failOnError: true)
}
}
And here is our controller:
class TestController {
def testService
def updateData() {
testService.updateDomain(1);
render "Data updated"
}
}
Also, when we try calling testService.updateDomain(1) from Grails console, it worked without issue.
-- End Update
Hoping someone in the Groovy/Grails projects encountered this (strange) behavior before:
We are trying to upgrade our current Grails 1.3.7 version to Grails 2.4.5 and getting StaleObjectStateException on a few places (when submitting a form)
The messages typically looks like:
Object of class [com.sra.cgms.workflow.WorkflowTaskHistory] with identifier [212430]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.package.workflow.WorkflowTaskHistory#212430]
Our environment configuration is:
We looked around the web and typically people are getting this exception when in a multi users environment. But this happens for us when testing locally as a single user. We tried quite a few suggestions:
None of the above helps. Here is a snippet in DataSource.groovy:
hibernate {
cache.use_second_level_cache = true
cache.use_query_cache = false
//cache.region.factory_class = 'org.hibernate.cache.SingletonEhCacheRegionFactory' // Hibernate 3
cache.region.factory_class = 'org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory' // Hibernate 4
singleSession = true // configure OSIV singleSession mode
flush.mode = 'manual' // OSIV session flush mode outside of transactional context
}
// environment specific settings
environments {
local {
dataSource {
dbCreate = "update" // one of 'create', 'create-drop','update'
url = "jdbc:jtds:sqlserver://localhost/test_local"
username="dbuser"
password="secret"
driverClassName="net.sourceforge.jtds.jdbc.Driver"
logSql = true
properties {
maxActive = 100
maxIdle = 25
minIdle = 5
initialSize = 5
testOnBorrow = true
validationInterval = 30*1000 //30 seconds
validationQuery = "SELECT 1"
//defaultTransactionIsolation = java.sql.Connection.TRANSACTION_READ_COMMITTED
}
}
}
}
Upvotes: 0
Views: 593
Reputation: 1
As it turns out, the source of this StaleObjectStateException issue doesn't have anything to do with the config or code.
We have in our BootStrap.groovy code to run several SQL scripts to initialize our database (MS SQL Server) at application start up. A few of those SQL scripts contain the following
SET NOCOUNT ON;
We believe that line causes SQL Server to always returns 0 for update statements (maybe other type of SQL statements as well). When Hibernate executes the update statement and examines the return value, it always find 0. Hibernate compares that with the expected value (which is 1 for domain.save() call). The expected value and the return value don't match so Hibernate think the data is stale, therefore it throws the StaleObjectStateException. Note that Hibernate does this checking whether you turn on version or not.
Hope this info help those out there with similar situation
Upvotes: 0