Grails中最简单的模型:
class Author {
String first_name
String last_name
static hasMany = [ books : Book]
static constraints = {
first_name()
last_name()
}
}
class Book {
String title
String subtitle
Integer pages
static belongsTo = [author: Author]
static constraints = {
title()
subtitle nullable: true
pages()
}
}
在Grails创建的默认scaffolded表单中,Author包含在一个名为" author.id"的表单字段中。执行保存功能时,Grails将author.id识别为表示Book对象之外的内容,使用id获取Author的实例,并将其附加到Book的新实例。
在我的应用中,我从新的“表单”中取出了“作者”字段。在Book控制器中,我尝试手动分配作者的ID(它保存在会话变量中。)
这些不能工作:
bookInstance.author.id = 1
bookInstance.author = Author.get(1)
当我在调试器中检查bookInstance之前进入验证之前,我可以看到bookInstance.author是一个完全有效的对象。验证触发后,bookInstance.author为空。
然而,这确实有效:
def writer = Author.get(1)
writer.addToBooks(bookInstance)
我认为在两个域类中从惰性加载到急切加载可能会修复它,但它没有。有人可以解释为什么最后一种方法有效,但前一种方法不适用吗?
答案 0 :(得分:0)
您需要设置关系的两个方面。 addToBooks
方法为您做了这样的事情 -
bookInstance.author = author
author.books.add(bookInstance)
我认为当grails数据绑定器看到类似author.id
的表单参数时,它会获取author.id
参数指定的作者并设置关系的每一面。
答案 1 :(得分:0)
您不应该真正设置域类的ID - Grails / GORM会为您管理此字段。
如果要添加标识符,例如从控制器中添加标识符,为什么不将它作为单独的属性(称为id
以外的其他属性)添加到域对象中。如果您愿意,可以给它一个唯一的约束,这将强制它可以用作查找它的键,如果你在映射中放入一个索引,你就可以快速查找它
class MyClassWithOtherId {
long myOtherId
static constraints = {
myOtherId unique: true
}
static mapping = {
myOtherId index: 'myOtherIndex_idx'
}
}
用法:
MyClassWithOtherId.findByMyOtherId(1)