如何使用 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 服务

如何对 GORM 子文档字段进行不同的查询?

Go GORM 有很多关系。如何将数据存储到MYSQL DB

Gorilla Mux 和 GORM 失败