2

我有使用集成测试和 Grails 脚手架将数据写入 mongoDB 数据库的问题。尝试从“列表”类型页面选择域实例时,我收到错误“[domain name] not found with id null”。

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

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

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

4

4 回答 4

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 类型。

于 2013-06-14T10:08:56.413 回答
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 的建议更新模板。

于 2013-10-04T11:30:37.787 回答
0

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

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/目录下的脚手架模板。然后你就有了新的脚手架,可以为你的所有域类生成定制的控制器、视图和测试。

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

于 2012-12-17T03:44:47.837 回答
0

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

在域类中:

ObjectId id

在各自的控制器中:

static scaffold = true

从 Mongo 清除所有现有集合

考虑到您已正确配置 mongo-plugin,我想这足以让 Grails-Mongo 应用程序启动并运行

于 2013-10-04T17:20:46.320 回答