何时在NHibernate / Hibernate OneToMany关系上使用inverse = false?


70

我一直试图了解Hibernate的inverse属性,但这似乎只是概念上困难的事情之一。

我得到的要点是,当您拥有一个使用一对多映射的Child对象集合的父实体(例如Parent)时,在映射上设置inverse = true会告诉Hibernate'另一面(子)有责任自行更新以维护其表中的外键引用。

在将Children添加到代码中的集合中,然后保存Parent(设置了cascade-all)时,这样做似乎有两个好处:您可以在数据库上保存不必要的命中(因为没有设置逆设置,Hibernate认为这样)有两个地方可以更新FK关系),并且根据官方文档:

如果关联的列声明为NOT NULL,则NHibernate在创建或更新关联时可能会导致约束冲突。为防止出现此问题,必须使用双向关联,将多个值端(集合或包)标记为inverse =“ true”。

到目前为止,这一切似乎都有意义。我不明白是这样的:你什么时候会希望使用逆=真正在一个一对多的关系?

Answers:


82

正如Matthieu所说,唯一不想设置inverse = true的情况是,孩子对自己进行更新没有任何意义,例如孩子不了解其父母。

让我们尝试一个现实世界,而不是完全没有人为的例子:

<class name="SpyMaster" table="SpyMaster" lazy="true">
  <id name="Id">
    <generator class="identity"/>
  </id>
  <property name="Name"/>
  <set name="Spies" table="Spy" cascade="save-update">
    <key column="SpyMasterId"/>
    <one-to-many class="Spy"/>
  </set>
</class>

<class name="Spy" table="Spy" lazy="true">
  <id name="Id">
    <generator class="identity"/>
  </id>
  <property name="Name"/>
</class>

间谍主管可以有间谍,但是间谍永远不知道自己的间谍主管是谁,因为我们没有在间谍类中包括多对一关系。同样(方便地),间谍可能会变成流氓,因此不需要与间谍主管关联。我们可以如下创建实体:

var sm = new SpyMaster
{
    Name = "Head of Operation Treadstone"
};
sm.Spies.Add(new Spy
{
    Name = "Bourne",
    //SpyMaster = sm // Can't do this
});
session.Save(sm);

在这种情况下,您可以将FK列设置为可空值,因为保存sm的行为会插入SpyMaster表和Spy表中,只有在此之后,它才会更新Spy表以设置FK。在这种情况下,如果我们将inverse = true设置为FK,则永远不会更新。


这对我不起作用。它从不运行更新。它只插入它们。
BradLaney 2012年

29

尽管大家都接受了很高的评价,但我还有另一个答案。

考虑具有以下关系的类图:

父=>项目列表
物品=>父母

从来没有说过,Item => Parent关系对于Parent => Items关系是多余的。一个项目可以引用任何父项。

但是在您的应用程序中,您知道这些关系是多余的。您知道这些关系不需要分别存储在数据库中。因此,您决定将其存储在单个外键中,从项指向父项。这些最少的信息足以建立列表引用。

您可以使用NH将其映射为:

  • 对两个关系使用相同的外键
  • 告诉NH一个(列表)对另一个是多余的,并且在存储对象时可以忽略。(这就是NH实际上所做的事情inverse="true"

这些是与逆相关的思想。没有其他的。这不是选择,只有一种正确的映射方法。


间谍问题如果要支持从项到父项的引用,则是完全不同的讨论。这取决于您的业务模型,NH对此不做任何决定。如果缺少一种关系,则当然不会有冗余,也不会使用逆关系。

误用:如果在不具有任何冗余的列表上使用inverse =“ true”,则不会存储该列表。如果未指定inverse =“ true”,则NH可能会将冗余信息存储两次。


我发现答案比公认的答案更好理解
r3try 2015年

比我的答案简单和切题
丹尼尔·席林

15

如果您想建立单向关联,即子代无法导航到父代。如果是这样,则FK列应为NULLABLE,因为子级将在父级之前保存。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.