2011-06-03 39 views
7

我必须在每个方向分配关系吗?使用textbook domain classes for the hasOne relationship,这似乎从我的测试,到目前为止必要得到实例承认对方:我是否需要在两个方向上分配Grails hasOne关系?

def face = new Face() 
def nose = new Nose() 
face.nose = nose 
nose.face = face 

我不知道为什么,虽然。这非常尴尬。我期待有更好的方法。

编辑:

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

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

+0

如果你澄清哪一部分是'尴尬'我可以扩大我的答案 – hvgotcodes 2011-06-03 02:52:51

+0

这是尴尬的需要*两个*任务完成工作。将它与face.addToEars(leftear)进行比较,它不需要我也指定leftear.face = face。 – 2011-06-03 13:05:43

+0

在我的回答中添加了更多内容 – hvgotcodes 2011-06-03 13:14:38

回答

17

直接回答

需要建立的关系,即分配鼻子面对和面对的节点,是不是真的很尴尬。休眠是一个关系映射器,所以你需要明确的关系。也就是说,通过在Face上定义一个

setNose(nose){ 
    this.nose = nose 
    nose.face = this 
} 

可以编写更少的代码。现在,当您执行face.nose = nose时,会为您调用setter,并以您想要的方式设置关系。

一般有用的思想

一般情况下,你并不需要分配在两个方向上的关系。 单向双向关系是完全有效的。

但是,hasOne定义具有非常具体的含义。该文档非常清楚地指出,hasOne的目的是告诉hibernate将定义关系的关键字放在孩子中,在这种情况下是鼻子。如果你仔细想一想,你会意识到应该是的双向关系。这里有几点想法:

1)你定义脸上的hasOne(即父母)。 2)即使你已经定义了父对象上的hasOne,受影响的基础表是子对象的表(即鼻子上的face_id列)
3)由于外键在子对象上,子对象必须有参考其父母。如果没有,你可能会有一个属于外键的属性,但与对象无关。
4)请记住,您正在使用ORM的机制来定义关系。虽然您可以手动将一个face_id字段添加到Nose中,并在代码中设置值(即自己管理关系并且不让ORM工具执行此操作),但显式使用ORM的事实意味着ORM工具将管理关系为你。

编辑 - 现在阅读我的答案,我不服气,所以我写了一个测试。我如hasOne文档中所示定义了Face和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,你有一个双向的关系异常。

+0

谢谢您对此答案的最新补充。如果您仅通过setNose()讨论添加第二个答案,我会接受它。这样,答案将直接针对我目前状态下的问题。 – 2011-06-03 15:14:02

+0

@jim我认为保持一个答案是更好的SO程序。但我重新格式化并重新排列了答案,重点是首先标记为这样 – hvgotcodes 2011-06-03 22:28:09