如何使用 GORM 为 Mongo 的低级 API 进行安全插入?
Posted
技术标签:
【中文标题】如何使用 GORM 为 Mongo 的低级 API 进行安全插入?【英文标题】:How to do safe inserts using GORM for Mongo's low-level API? 【发布时间】:2011-10-14 21:39:05 【问题描述】:我正在尝试使用 GORM 为 Mongo 的低级 API 进行安全插入。
我在一个干净的 Grails 项目中重现了这个问题,如下所示:
-
创建一个新的 Grails 项目
卸载 Hibernate 插件
为 Mongo 插件安装 GORM
使用以下操作创建控制器
import com.mongodb.*
class TestController
def mongo
def index =
def database = mongo.getDB("ExampleDatabase")
def collection = database.getCollection("ExampleCollection")
def document = new BasicDBObject();
document.put("key", "value")
collection.insert(document, WriteConcern.SAFE)
render ""
触发动作时,抛出以下异常:
2011-07-27 12:53:03,161 [http-8080-1] ERROR errors.GrailsExceptionResolver - Exception occurred when processing request: [GET] /WriteConcern.SAFE-test/test/index
Stacktrace follows:
groovy.lang.MissingPropertyException: No such property: value for class: com.mongodb.WriteConcern
at com.gmongo.internal.Patcher$__converAllCharSeqToString_closure2.doCall(Patcher.groovy:81)
at com.gmongo.internal.Patcher._converAllCharSeqToString(Patcher.groovy:80)
at com.gmongo.internal.Patcher$_converAllCharSeqToString.callStatic(Unknown Source)
at com.gmongo.internal.Patcher$_converAllCharSeqToString.callStatic(Unknown Source)
at com.gmongo.internal.Patcher._convert(Patcher.groovy:69)
at com.gmongo.internal.Patcher$_convert.callStatic(Unknown Source)
at com.gmongo.internal.Patcher$__patchInternal_closure1.doCall(Patcher.groovy:31)
at writeconcern.safe.test.TestController$_closure1.doCall(TestController.groovy:17)
at writeconcern.safe.test.TestController$_closure1.doCall(TestController.groovy)
at java.lang.Thread.run(Thread.java:680)
如果我将操作更改为使用 Mongo Java API,如下所示:
def index =
def database = new Mongo().getDB("ExampleDatabase")
def collection = database.getCollection("ExampleCollection")
def document = new BasicDBObject();
document.put("key", "value")
collection.insert(document, WriteConcern.SAFE)
render ""
现在它可以工作了,文档按预期保存到 Mongo 数据库中。
我的问题是:这是 GMongo 包装器的错误,或者应该如何使用低级 API 完成安全写入?
【问题讨论】:
【参考方案1】:这是由于 GMongo 库以及它如何修补 DBCollection
对象以处理将 Map
对象传递给 insert
方法并转换它们的方式。它假定insert
方法的所有参数都是Map
对象,然后将尝试从Map.Entry
获取value
属性。
查看source of Patcher.groovy from GMongo library,您会看到尝试执行此操作的函数_convert()
。它看起来像是 Github 项目的一个分支,需要对参数进行类型检查(要么查看它是否是 WriteConcern
,要么在传递给 _converAllCharSeqToString
之前检查它是否实际上是 Map
)是必要的。
编辑:
我在 Github 上创建了一个 pull request 以进行适当的代码更改,但与所有 Groovy 一样,修补类也有帮助。您可以在 BootStrap.groovy
中“修补”WriteConcern
类以拥有 getValue
方法,这样您就可以将参数传入:
def init = servletContext ->
com.mongodb.WriteConcern.metaClass.getValue = null
【讨论】:
感谢您的解释。像你说的那样对 WriteConcern 类进行猴子修补效果很好。以上是关于如何使用 GORM 为 Mongo 的低级 API 进行安全插入?的主要内容,如果未能解决你的问题,请参考以下文章
Grails Mongo GORM 插件 - 浮点和字节的映射是字符串而不是数字
如何使用 Gin 和 Gorm 搭建一个简单的 API 服务
如何使用 Gin 和 Gorm 搭建一个简单的 API 服务