我是否需要在两个方向上分配Grails hasOne关系?

时间:2011-06-03 01:30:03

标签: grails gorm

我必须在每个方向分配关系吗?使用textbook domain classes for the hasOne relationship,到目前为止,我的测试似乎有必要让实例相互识别:

def face = new Face()
def nose = new Nose()
face.nose = nose
nose.face = face
但是,我不知道为什么。这是非常尴尬的。我期待有更好的方法。

编辑:

我需要关系分配的帮助。我不需要有关在域类中建立hasOne关系的机制的信息,或者关于双向引用的智慧的讨论。我想知道为什么只需要单个语句来设置nose实例和face实例之间的关系。

我的双语句解决方案基于我在复杂应用程序中遇到的麻烦。我将尝试在一个简单的例子中重现我的经验。

1 个答案:

答案 0 :(得分:17)

直接回答

建立关系的需要,即分配鼻子到脸部和面对节点,并不是很尴尬。 Hibernate是一个 RELATIONSHIP 映射器,因此您需要使关系显式化。也就是说,您可以通过定义

来编写更少的代码
setNose(nose){
   this.nose = nose
   nose.face = this
}
在脸上

现在当你执行face.nose = nose时,会为你调用setter,并按照你想要的方式设置关系。

一般有用的想法

通常,您无需在两个方向上分配关系。拥有单向双向关系是完全有效的。

但是,hasOne定义具有非常具体的含义。文档非常清楚地说明了hasOne的目的是告诉hibernate将定义关系的键放在子节点中,在本例中为Nose。如果你仔细考虑它,你会发现的关系应该是双向的。以下是思路:

1)你在脸上定义了hasOne(即父母) 2)即使您在父项上定义了hasOne,受影响的基础表也是子表(即Nose上的face_id列)
3)由于外键在孩子身上,孩子必须引用其父母。如果没有,您将在子项上拥有属于外键但与对象无关的属性 4)请记住,您正在使用ORM的机器来定义关系。虽然您可以手动将face_id字段添加到Nose,并在代码中设置值(即自己管理关系而不让ORM工具执行此操作),但是您明确使用ORM这一事实意味着ORM工具将管理关系对你而言。

编辑 - 现在读我的答案,我不相信,所以我写了一个测试。我定义了face和Nose类,如hasOne文档中所示,但我没有在鼻子上定义Face。我试图让它单向。我写了一个测试,看看会发生什么。这是测试

class FaceTests extends GroovyTestCase {

    public void testStuff(){
        Face face = new Face()
        Nose nose = new Nose()

        face.nose = nose;
        face.save(flush:true)

        assertNotNull face.id
        assertNotNull nose.id
    }

}

,结果是一个包含

的异常
hasOne property [Face.nose] is not bidirectional. Specify the other side of the relationship!

因此,框架甚至可以确保,当您使用hasOne时,您将拥有双向关系。