Grails with MongoDB,Object id和scaffold

时间:2012-12-17 01:24:30

标签: mongodb grails scaffold objectid

我使用集成测试和Grails脚手架将数据写入mongoDB数据库。当尝试从“列表”类型页面中选择域实例时,我收到错误“找不到[域名],ID为null”。

我确信这是因为Grails url [controller] / [action] / [id]。此id是一个字符串,需要转换为Grails查询的ObjectId。

有没有办法做到这一点,以便它影响指定的域甚至更好,所有域一次?

我想当我正在编写我的应用程序时,我可以在action方法中将其转换为ObjectId,但我希望脚手架能够工作或提供全局解决方案。

4 个答案:

答案 0 :(得分:1)

我相信这种情况正在发生,因为show()方法(Grails脚手架功能作为动作生成)接受类型为Long的id参数。

def show(Long id) {
    def suiteInstance = Suite.get(id)
    if (!suiteInstance) {
        flash.message = message(code: 'default.not.found.message', args: [message(code: 'suite.label', default: 'MyDomainClass'), id])
        redirect(action: "list")
        return
    }

    [suiteInstance: suiteInstance]
}

将id参数绑定到参数。由于ObjectId无法转换为Long,因此最终为null,因此对MyDomainClass.get(id)的调用失败并显示错误消息。

你可以通过覆盖你的脚手架控制器中的show()动作来解决这个问题,以便它需要一个ObjectId或String,但我想说这个问题的正确解决方法是更新Grails脚手架插件让它更多一些它所接受的ID类型中的自由主义。

答案 1 :(得分:1)

我也有这个问题。您可以将域对象ID保留为ObjectId并按如下方式更新控制器:

域对象:

import org.bson.types.ObjectId;

class DomainObject {
        ObjectId id
        // Add other member variables...
}

控制器:

def show(String id) {
    def domainObjectInstance = domainObject.get(new ObjectId(id))
    if (!domainObjectInstance) {
        flash.message = message(code: 'default.not.found.message', args: [message(code: 'domainObject.label', default: 'DomainObject'), id])
        redirect(action: "list")
        return
    }

    [domainObjectInstance: domainObjectInstance]
}

您还需要更新其他使用id的控制器方法,例如编辑,更新等。

此外,如果您希望grails默认控制器生成对所有域对象都这样工作,您可以像coderLMN建议的那样更新模板。

答案 2 :(得分:0)

show()方法中的get(params.id)调用不会将params.id字符串转换为ObjectId对象,因此域实例将为null,然后以下代码将您列出具有错误消息的操作:

if (!exampleInstance) {
    flash.message = message(code: 'default.not.found.message', args: [message(code: 'example.label', default: 'Example'), params.id])
    redirect(action: "list")
    return
}

可能的解决方案:

  1. 您可以运行“grails install-template”命令,以便可以修改src / templates / scaffolding /目录中的脚手架模板。然后,您可以使用新的脚手架为所有Domain类生成自定义控制器,视图和测试。

  2. 更简单的解决方案是将id属性定义为String而不是ObjectId。 String id将等于objectId.toString(),在这种情况下,您的脚手架将起作用。

答案 3 :(得分:0)

在域类中,将id类型保存为ObjectId,并为所有相应的控制器保持scaffold = true。

在Domain类中:

ObjectId id

在相应的控制器中:

static scaffold = true

清除Mongo的所有现有馆藏

我想这足以让Grails-Mongo应用程序和&运行,考虑到你已正确配置mongo-plugin