Grails / GORM:手动将一个对象的实例分配给另一个对象的实例在保存时失败

时间:2015-03-01 00:25:01

标签: hibernate grails gorm one-to-many

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)

我认为在两个域类中从惰性加载到急切加载可能会修复它,但它没有。有人可以解释为什么最后一种方法有效,但前一种方法不适用吗?

2 个答案:

答案 0 :(得分:0)

您需要设置关系的两个方面。 addToBooks方法为您做了这样的事情 -

bookInstance.author = author
author.books.add(bookInstance)

我认为当grails数据绑定器看到类似author.id的表单参数时,它会获取author.id参数指定的作者并设置关系的每一面。

答案 1 :(得分:0)

您不应该真正设置域类的ID - Grails / GORM会为您管理此字段。

请参阅以下帖子:herehere

如果要添加标识符,例如从控制器中添加标识符,为什么不将它作为单独的属性(称为id以外的其他属性)添加到域对象中。如果您愿意,可以给它一个唯一的约束,这将强制它可以用作查找它的键,如果你在映射中放入一个索引,你就可以快速查找它

class MyClassWithOtherId {
    long myOtherId

    static constraints = {
        myOtherId unique: true
    }

    static mapping = {
        myOtherId index: 'myOtherIndex_idx'
    }
}

用法:

MyClassWithOtherId.findByMyOtherId(1)