我使用集成测试和Grails脚手架将数据写入mongoDB数据库。当尝试从“列表”类型页面中选择域实例时,我收到错误“找不到[域名],ID为null”。
我确信这是因为Grails url [controller] / [action] / [id]。此id是一个字符串,需要转换为Grails查询的ObjectId。
有没有办法做到这一点,以便它影响指定的域甚至更好,所有域一次?
我想当我正在编写我的应用程序时,我可以在action方法中将其转换为ObjectId,但我希望脚手架能够工作或提供全局解决方案。
答案 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 }
可能的解决方案:
您可以运行“grails install-template”命令,以便可以修改src / templates / scaffolding /目录中的脚手架模板。然后,您可以使用新的脚手架为所有Domain类生成自定义控制器,视图和测试。
更简单的解决方案是将id属性定义为String而不是ObjectId。 String id将等于objectId.toString(),在这种情况下,您的脚手架将起作用。
答案 3 :(得分:0)
在域类中,将id类型保存为ObjectId,并为所有相应的控制器保持scaffold = true。
在Domain类中:
ObjectId id
在相应的控制器中:
static scaffold = true
清除Mongo的所有现有馆藏
我想这足以让Grails-Mongo应用程序和&运行,考虑到你已正确配置mongo-plugin