【问题标题】:Grails 2.3.7 Optimistic Locking version is updated every time a Command Object is submittedGrails 2.3.7 Optimistic Locking 版本在每次提交命令对象时更新
【发布时间】:2014-06-08 14:18:07
【问题描述】:

我有以下

def save(ACommand command){
  ...
}

@Validateable
class ACommand implements Serializable
{
  ADomainObject bundleDef
}

但每次调用 save 时版本都会增加。因此,如果我打开两个浏览器并连续提交不同的值,而不是像我预期的那样第二次出现错误,则值会更新。

我也尝试过使用两个不同的会话,没有区别

更新

如果我使用断点并在另一个完成之前提交它工作正常。但是,如果我让第一个完成然后提交第二个而不刷新,则版本会更新为较新的版本(我不想要)并且更改会通过。

更新 2

当您执行更新时,Hibernate 将自动检查版本属性与数据库中的版本列,如果它们不同,将抛出 StaleObjectException。如果事务处于活动状态,这将回滚事务。

per Grails 在我看来这应该可行。

【问题讨论】:

  • 您能否展示一下保存实现,看看控制器中如何处理乐观锁定情况?否则代码 sn-p 没有多大意义,谢谢 :)
  • 我正在使用 Grails 中的自动锁定功能,不确定您想看到什么?它只是从一个非常基本的东西中保存一个对象

标签: grails grails-orm optimistic-locking


【解决方案1】:

AFAIK,您需要自己检查版本并处理故障 - 它不会自动发生。你可以用这样的代码来做到这一点:

/**
 * Returns a boolean indicating whether the object is stale
 */
protected boolean isStale(persistedObj, versionParam = params.version) {

    if (versionParam) {
        def version = versionParam.toLong()
        if (persistedObj.version > version) {
            return true
        }
    } else {
        log.warn "No version param found for ${persistedObj.getClass()}"
    }
    false
}

您可以通过这样的操作调用isStale

def update() {
    Competition competition = Competition.get(params.id)

    if (isStale(competition)) {
        // handle stale object
        return
    }

    // object is not stale, so update it
}

【讨论】:

  • 我对这个答案有 2 个问题。 1.)这不适用于场景和命令对象(如我所示),因为在序列化时它必须在某处进行获取,因此我获得的内置版本高于应有的版本,这意味着 persistedObj.version > version 是总是正确的。除非我用断点来做,否则上面的工作正常。 2.) 我认为 Grails 中乐观锁定的整个想法是为了防止创建这种类型的手动代码?
  • 1) 如果对象不是陈旧的,那么参数中发送的版本应该 == 数据库中的版本 2) AFAIK,您需要自己检查版本,它不会自动发生。如果你查看一个脚手架控制器的源代码,你会看到类似于上面的代码
  • 实际上我必须在 GSP 中添加一个 myVersion 标签才能保留它。否则它会自动增加到更高版本。将非持久版本属性与持久版本属性进行比较有助于我确定它是否过时。
【解决方案2】:

我不确定您期望发生什么,但您所描述的对我来说听起来是正确的,除非您的 save() 操作中有相关的代码。

你不能指望 Hibernate 在这里做任何特别的事情。当调用 save() 操作时,使用 Hibernate 检索实例,对其进行变异然后保存。就 Hibernate 而言,这一切都很好。

解决此问题的一种方法是在呈现用于编辑实体的表单时,将正在编辑的实体的版本呈现到隐藏的表单字段,该字段将在保存实体时提交。在从数据库中检索实体后的保存操作中,将其版本与从隐藏表单字段中检索到的版本进行比较,如果它们不匹配,则您知道实体在这两个步骤之间已被修改,您可以做出反应,但适合您的应用程序。请注意,由于您的示例使用的是命令对象,因此在您的代码执行之前将数据绑定强加于实体。如果这不是您想要的,请不要使用命令对象。

希望对你有帮助。

【讨论】:

  • 就命令对象而言。生态系统中的域对象是否有更简单的 NvP 序列化器/反序列化器形式?
  • @Jackie 我不确定你在问什么。您可以非常轻松地序列化到 JSON 或从 JSON 序列化。这就是你要找的东西吗?
  • RT 但多部分表单作为名称值对返回,因此在支持 json 表单提交之前,序列化为 JSON 对我没有任何作用
  • 支持 JSON 表单提交。
  • 好的,我以为它们还没有实现,但我可以调查一下。
猜你喜欢
  • 2019-03-30
  • 2020-05-07
  • 2012-01-19
  • 2018-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-09
  • 2020-04-20
相关资源
最近更新 更多