Grails2.3.7乐观锁定版本在每次提交命令对象时都会更新

Grails2.3.7乐观锁定版本在每次提交命令对象时都会更新,grails,gorm,optimistic-locking,Grails,Gorm,Optimistic Locking,我有以下几点 def save(ACommand command){ ... } @Validateable class ACommand implements Serializable { ADomainObject bundleDef } 但每次调用save时,版本都会递增。因此,如果我打开两个浏览器并连续提交一个不同的值,而不是像我预期的那样在第二次出现错误,那么该值将被更新 我还尝试使用两种不同的会话,没有任何区别 更新 如果我使用断点并在另一个断点完成之前提交,那么它可以正

我有以下几点

def save(ACommand command){
  ...
}

@Validateable
class ACommand implements Serializable
{
  ADomainObject bundleDef
}
但每次调用save时,版本都会递增。因此,如果我打开两个浏览器并连续提交一个不同的值,而不是像我预期的那样在第二次出现错误,那么该值将被更新

我还尝试使用两种不同的会话,没有任何区别

更新

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

更新2

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


在我看来,这应该是可行的。

好吧,你需要自己检查版本并处理故障-这不是自动发生的。您可以使用如下代码执行此操作:

/**
 * 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
}

我不确定您预期会发生什么,但您描述的内容对我来说是正确的,除非您的save()操作中有相关的代码

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

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


我希望这会有所帮助。

您能展示一下save的实现,看看控制器中乐观锁是如何处理的吗?否则代码片段就没有什么意义了,thx:)我正在使用Grails中的自动锁定不确定您想看到什么?它只是从表单中保存了一个对象。这是我在回答这个问题时遇到的非常基本的问题。1.)这不适用于场景和命令对象(如我所示),因为在序列化时,它必须执行get-Anywhere操作,因此我获得的内置版本高于它应该的版本,这意味着persistedObj.version>version始终为真。除非我使用断点,否则上面的方法很好。2.)我认为Grails中乐观锁定的整个想法是为了防止创建这种类型的手动代码?1)如果对象没有过时,那么在参数中发送的版本应该==数据库中的版本2)好的,您需要自己检查版本,它不会自动发生。如果你看一看脚手架控制器的源代码,你会看到与上面类似的代码实际上我不得不在GSP中添加一个myVersion标签来保存它。否则它会自动增加到更高的版本。将非持久化版本属性与上的持久化版本属性进行比较有助于我确定它是否过时。生态系统中的域对象是否有更简单的形式NvP序列化器/反序列化器?@Jackie我不知道你在问什么。您可以非常轻松地序列化到JSON或从JSON进行序列化。这就是你要找的东西吗?部分但多部分表单以名称-值对的形式返回,所以在支持JSON表单提交之前,序列化为JSON对我没有任何帮助。支持JSON表单提交。好的,我认为它们还没有实现,我可以研究一下。