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

我是否需要在两个方向上分配Grails hasOne关系?,grails,gorm,Grails,Gorm,我必须在每个方向分配关系吗?使用,从我目前的测试来看,这似乎是必要的,以使实例相互识别: def face = new Face() def nose = new Nose() face.nose = nose nose.face = face 但我不知道为什么。而且非常尴尬。我期待有更好的办法 编辑: 我需要你帮我处理人际关系任务。我不需要关于在域类中建立hasOne关系的机制的信息,也不需要关于双向引用的智慧的讨论。我想知道为什么设置nose实例和face实例之间的关系需要不止一条语句 我

我必须在每个方向分配关系吗?使用,从我目前的测试来看,这似乎是必要的,以使实例相互识别:

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

编辑:

我需要你帮我处理人际关系任务。我不需要关于在域类中建立hasOne关系的机制的信息,也不需要关于双向引用的智慧的讨论。我想知道为什么设置nose实例和face实例之间的关系需要不止一条语句


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

直接回答

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

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的机制来定义关系。虽然您可以手动在Nose中添加一个face_id字段,并在代码中设置值(即,自己管理关系,而不是让ORM工具来管理关系),但您使用ORM的事实明确表示ORM工具将为您管理关系

编辑--现在读我的答案,我不相信,所以我写了一个测试。我定义了Face和Nose类,如hasOne文档中所示,但没有定义Nose上的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时,你有一种双向关系。

如果你澄清哪一部分是“尴尬”的,我可以扩展我的回答。完成工作需要两个任务是尴尬的。将其与face.addToEars(leftear)进行比较,后者不要求我也指定leftear.face=face。感谢您最近添加了此答案。如果您只在setNose()讨论中添加第二个答案,我将接受它。这样,答案将直接针对我当前状态下的问题。@jim我认为保留一个答案更好,所以请按程序执行。但我重新格式化并重新排列了主要问题的答案是“第一”,并标记为“第一”