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

Jim*_*man 7 grails grails-orm

我必须在每个方向分配关系吗?使用教科书域类来实现hasOne关系,从我的测试到目前为止,这似乎是必要的,以使实例能够相互识别:

def face = new Face()
def nose = new Nose()
face.nose = nose
nose.face = face
Run Code Online (Sandbox Code Playgroud)

不过我不知道为什么.这是非常尴尬的.我期待有更好的方法.

编辑:

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

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

hvg*_*des 17

直接回答

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

setNose(nose){
   this.nose = nose
   nose.face = this
}
Run Code Online (Sandbox Code Playgroud)

在脸上.现在,当你这样做时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
    }

}
Run Code Online (Sandbox Code Playgroud)

结果是包含的异常

hasOne property [Face.nose] is not bidirectional. Specify the other side of the relationship!
Run Code Online (Sandbox Code Playgroud)

因此,对于您来说,框架甚至可以确保当您使用hasOne时,您具有双向关系.