【问题标题】:When to use inverse=false on NHibernate / Hibernate OneToMany relationships?何时在 NHibernate / Hibernate OneToMany 关系上使用 inverse=false?
【发布时间】:2009-06-30 00:06:27
【问题描述】:

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

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

在代码中将子项添加到集合中,然后保存父项(设置了 cascade-all)时,这样做似乎有 2 个好处:you save an unneccessary hit on the database(因为没有反向设置,Hibernate 认为它有两个更新FK关系的地方),并根据官方文档:

如果一个列 关联被声明 NOT NULL,NHibernate 可能会导致 创建时违反约束 或更新关联。阻止 这个问题,你必须使用 双向关联 许多有价值的末端(套装或袋子) 标记为 inverse="true"。

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

【问题讨论】:

    标签: nhibernate hibernate collections one-to-many inverse


    【解决方案1】:

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

    【讨论】:

    • 这对我不起作用。它从不运行更新。它只插入它们。
    【解决方案2】:

    尽管被高票接受的答案,我有另一个答案。

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

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

    没有人曾经说过,Item => Parent 关系对于 Parent => Items 关系是多余的。一个 Item 可以引用任何 Parent。

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

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

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

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


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

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

    【讨论】:

    • 我发现这个答案比接受的答案更容易理解
    • 比我的answer简单多了。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-08
      • 2019-06-29
      • 2014-12-22
      • 2015-09-18
      • 1970-01-01
      • 2012-08-14
      • 1970-01-01
      • 2013-05-09
      相关资源
      最近更新 更多