Grails Gorm + mongoDb在保存OptimisticLockingException期间获取

时间:2013-10-21 20:40:11

标签: mongodb grails gorm

我在grails服务中尝试保存mongodb中的对象:

Cover saveCover = new Cover()
saveCover.id = url
saveCover.url = url
saveCover.name = name
saveCover.sku = sku
saveCover.price = price

saveCover.save()

封面域看起来像这样:

class Cover {

    String id
    String name
    String url
    String sku
    String price
}

所以我希望基于url拥有自定义ID,但在保存过程中我收到错误:

  

无法提交数据存储区事务;嵌套异常是   org.grails.datastore.mapping.core.OptimisticLockingException:The   在您编辑时,其他用户更新了实例

但我没有使用setter,只是在构造函数中传递所有值,这个异常消失了。为什么呢?

2 个答案:

答案 0 :(得分:2)

正如documentation中所述:

  

请注意,如果您手动分配标识符,则需要使用insert方法而不是save方法,否则GORM无法确定您是要尝试实现插入还是更新

所以你需要使用insert方法而不是在分配id生成器时保存

cover.insert(failOnError: true)

如果您没有像这样定义映射:

static mapping = {
    id generator: 'assigned'
}

并将使用insert方法,您将获得一个自动生成的objectId:

"_id" : "5496e904e4b03b155725ebdb"

答案 1 :(得分:1)

当您为新模型分配id并尝试保存它时会发生此异常,因为GORM认为它应该进行更新。

为什么会发生此异常

当我遇到这个问题时,我使用的是1.3.0的grails-mongo插件。这使用了1.1.9的grails数据存储区核心代码。我注意到在847(ish) of NativeEntryEntityPersister行上生成了异常。此代码更新db中的现有域对象。

Above that on line 790是创建isUpdate的地方,用于查看是否为更新。 isInsertfalse,因为强制插入时只有truereadObjectIdentifier将返回已分配给对象的ID,因此isUpdate将结束评估为真。

修复异常

感谢第791行的&& !isInsert如果强制插入,则会调用插入代码,并确保异常消失。但是,当我这样做时,未保存分配的ID,而是使用生成的对象ID。我看到对此的修复是在line 803,它检查生成器是否设置为"assigned"

要解决此问题,您可以添加以下映射。

class Cover {
    String id
    String name
    String url
    String sku
    String price
    static mapping = {
        id generator: 'assigned'
    }
}

这样做的副作用是您始终需要为新的Cover域对象分配id。