【问题标题】:How to do safe inserts using GORM for Mongo's low-level API?如何使用 GORM 为 Mongo 的低级 API 进行安全插入?
【发布时间】:2011-10-14 21:39:05
【问题描述】:

我正在尝试使用 GORM 为 Mongo 的低级 API 进行安全插入。

我在一个干净的 Grails 项目中重现了这个问题,如下所示:

  1. 创建一个新的 Grails 项目
  2. 卸载 Hibernate 插件
  3. 为 Mongo 插件安装 GORM
  4. 使用以下操作创建控制器

    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 ""
    
        }
    }
    
  5. 触发动作时,抛出以下异常:

    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)
    
  6. 如果我将操作更改为使用 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 ""
    
    }
    
  7. 现在它可以工作了,文档按预期保存到 Mongo 数据库中。

我的问题是:这是 GMongo 包装器的错误,或者应该如何使用低级 API 完成安全写入?

【问题讨论】:

    标签: grails mongodb grails-orm


    【解决方案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 类进行猴子修补效果很好。
    猜你喜欢
    • 1970-01-01
    • 2015-02-04
    • 2018-10-07
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 2021-12-15
    • 1970-01-01
    相关资源
    最近更新 更多