70

我一直试图掌握 Hibernate 的逆属性,它似乎只是概念上困难的事情之一。

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

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

如果关联的列被声明为 NOT NULL,NHibernate 在创建或更新关联时可能会导致违反约束。为防止此问题,您必须使用与标记为 inverse="true" 的多值端(集合或包)的双向关联。

到目前为止,这一切似乎都说得通。我不明白的是:你什么时候不想在一对多的关系上使用 inverse=true ?

4

3 回答 3

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>

Spymasters 可以有间谍,但间谍永远不知道他们的 spymaster 是谁,因为我们没有在 spy 类中包含多对一的关系。此外(方便地)间谍可能会变成流氓,因此不需要与间谍大师相关联。我们可以如下创建实体:

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 将永远不会更新。

于 2009-07-01T08:02:18.320 回答
29

尽管得到了高票接受的答案,但我对此还有另一个答案。

考虑具有这些关系的类图:

父级 => 项目列表
项目 => 父级

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

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

用 NH 映射它所需要做的就是:

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

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


间谍问题:如果你想支持从 Item 到 Parent 的引用,这是一个完全不同的讨论。这取决于您的商业模式,NH 不会对此做出任何决定。如果缺少其中一个关系,当然就没有冗余,也没有使用逆。

误用:如果您在内存中没有任何冗余的列表上使用 inverse="true",它就不会被存储。如果你没有指定 inverse="true" 如果它应该在那里,NH 可能会存储两次冗余信息。

于 2011-02-04T09:06:18.827 回答
15

如果你想有一个单向关联,即孩子不能导航到父母。如果是这样,您的 FK 列应该为 NULLABLE,因为子级将在父级之前保存。

于 2009-06-30T20:57:52.337 回答