- 更新: 事实证明,我们根本无法更新任何域对象。我们创建了非常简单的域/服务/控制器组合,并且仍然获得了StaleObjectStateException:Row被另一个事务更新或删除(或者unsaved-value映射不正确):[com.sra.cgms.test.TestDomain#1] 这是我们的域类
class TestDomain {
static mapping = {
table name:'TEST_DOMAIN', schema:'cgms'
id generator:'identity', column:'id', sqlType: 'int'
}
String someVal
static constraints = {
someVal(nullable: true)
}
}
这是我们的服务类:
class TestService {
public void updateDomain(int domainId) {
TestDomain testDomain = TestDomain.get(1)
testDomain.someVal = "updated Val"
testDomain.save(flush: true, failOnError: true)
}
}
这是我们的控制器:
class TestController {
def testService
def updateData() {
testService.updateDomain(1);
render "Data updated"
}
}
此外,当我们尝试从Grails控制台调用testService.updateDomain(1)时,它没有问题。
- 结束更新
希望Groovy / Grails项目中有人在遇到此(奇怪)行为之前:
我们正在尝试将当前的Grails 1.3.7版本升级到Grails 2.4.5并在几个地方获取StaleObjectStateException(提交表单时)
消息通常如下:
具有标识符[212430]的类[com.sra.cgms.workflow.WorkflowTaskHistory]的对象:乐观锁定失败;嵌套异常是org.hibernate.StaleObjectStateException:Row被另一个事务更新或删除(或unsaved-value映射不正确):[com.package.workflow.WorkflowTaskHistory#212430]
我们的环境配置是:
我们环顾网络,通常人们在多用户环境中会遇到此异常。但在本地作为单个用户进行测试时,这种情况就会发生。我们尝试了很多建议:
以上都没有帮助。以下是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
}
}
}
}
答案 0 :(得分:0)
事实证明,这个StaleObjectStateException问题的根源与配置或代码没有任何关系。
我们在BootStrap.groovy代码中运行多个SQL脚本来在应用程序启动时初始化我们的数据库(MS SQL Server)。其中一些SQL脚本包含以下
SET NOCOUNT ON;
我们认为该行导致SQL Server始终为更新语句返回0(也可能是其他类型的SQL语句)。当Hibernate执行update语句并检查返回值时,它总是找到0. Hibernate将其与期望值(domain.save()调用为1)进行比较。预期值和返回值不匹配,因此Hibernate认为数据是陈旧的,因此它会抛出StaleObjectStateException。请注意,Hibernate会检查您是否打开版本。
希望这些信息可以帮助那些有类似情况的人