Grails 2 StaleObjectStateException

时间:2015-09-03 22:14:45

标签: hibernate grails groovy

- 更新: 事实证明,我们根本无法更新任何域对象。我们创建了非常简单的域/服务/控制器组合,并且仍然获得了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]

我们的环境配置是:

  • Groovy 2.3,Grails 2.4.5,Hibernate 4.3.8.1(也尝试过3.6.10.18),SQL Server 2008,JTDS JDBC驱动程序1.2.5(也尝试过1.3.1)

我们环顾网络,通常人们在多用户环境中会遇到此异常。但在本地作为单个用户进行测试时,这种情况就会发生。我们尝试了很多建议:

  • 关闭Hibernate乐观锁定(在GORM域实体中禁用版本)
  • 在保存到db ..
  • 之前锁定对象

以上都没有帮助。以下是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
   }
  }
 }
}

1 个答案:

答案 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会检查您是否打开版本。

希望这些信息可以帮助那些有类似情况的人