我一直试图了解Hibernate的inverse属性,但这似乎只是概念上困难的事情之一。
我得到的要点是,当您拥有一个使用 一对多 映射的Child对象集合的父实体(例如Parent)时,在映射上设置inverse = true会告诉Hibernate’另一面(子)有责任自行更新以维护其表中的外键引用。
在将Children添加到代码中的集合中,然后保存Parent(设置了cascade- all)时,这样做似乎有两个好处:您可以在数据库上保存不必要的命中(因为没有设置反向,Hibernate认为这样)有两个地方可以更新FK关系),并且根据官方文档:
如果关联的列声明为NOT NULL,则NHibernate在创建或更新关联时可能会导致约束冲突。为避免此问题,您必须使用双向关联,并将多个有价值的末端(集合或袋子)标记为inverse =“ true”。
到目前为止,这一切似乎都是有道理的。我不明白是这样的:你什么时候会 不 希望使用逆=真正在一个一对多的关系?
正如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,则永远不会更新。