我在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,只是在构造函数中传递所有值,这个异常消失了。为什么呢?
答案 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
的地方,用于查看是否为更新。 isInsert
为false
,因为强制插入时只有true
,readObjectIdentifier
将返回已分配给对象的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。