我具有invoice
和invoiceParents
和one-to-many
的数据库结构,inverse
等于"false"
,而cascade
等于"all-delete-orphan"
。在.hbm
中针对父母和孩子的一些摘要下方。
父母:
<id name="InvoiceId" column="INVOICEKEYID" unsaved-value="0">
<generator class="sequence">
<param name="sequence">SOME_SEQ</param>
</generator>
</id>
...
<bag name="Partners" table="PARTNER" cascade="all-delete-orphan" inverse="false" lazy="true">
<key column="INVOICEKEYID"/>
<one-to-many class="Partner"/>
</bag>
孩子:
<id name="Id" column="PARTNERKEYID" unsaved-value="0">
<generator class="sequence">
<param name="sequence">ANOTHER_SEQ</param>
</generator>
</id>
...
<many-to-one name="Invoice" column="INVOICEKEYID" class="Invoice" />
当我第一次创建saveOrUpdate(invoice)
时,对于invoice和invoicePartners,有INSERT语句,其中fk为空,在其后为UPDATE语句,对于invoicePartners,则具有正确的fk。直到这一次一切正常。
当我要更新时,对于invoicePartners只有INSERT,对于发票只有一个UPDATE。没有针对invoicePartners的UPDATE或DELETE AND INSERT。
我在vs输出中观看它。
nHibernate如何工作?首先,我应该删除合作伙伴,然后插入新的合作伙伴,否则nHibernate将自动更新它?
答案 0 :(得分:1)
所有这些都源自您拥有的bag
(inverse="false"
)。通常,永远不要创建拥有包,带有(bag
)的inverse="true"
可提供最终的性能,因为操作不会失败。
在这种情况下,请注意不要以PK违规告终,NHibernate不会处理插入违反invoicePartner
的PK的情况,因为您已经告诉您这是一个PK违规行为。 bag
,而不是set
。如果您没有PK并希望重复invoicePartner
,则继续执行bag
,如果没有,请切换到set
。显然,如果您的class
内部确保了这一点,那么您将避免此问题。
尽管通常要谨慎使用bag
,但由于可以识别映射的实体,因此我认为这种情况很好,因此您应该获得与set
类似的性能。但是,如果无法识别它们,则NHibernate将必须删除所有子项,并在进行任何集合更改时将它们全部重新插入!
在invoicePartner
上添加invoice
:
invoicePartner
不会保存该关系,因为您已经告知映射,您希望invoice
拥有它。
因此,在对数据库进行任何插入或更新时,invoicePartner
无法填写INVOICEKEYID
列。
因此,父invoice
会一直等到invoicePartner
存在于数据库中,然后再更新外键列,如您观察到的那样。
根据默认行为,此更新可能会完全浪费时间,因为在我看来孩子会已经自己保存了此外键!
在invoicePartner
集合的更新中:
您所说的内容并不合适。如果您所做的只是更改invoice
集合,NHibernate将不会调用invoiceParnter
的更新。 invoice
表上没有任何更新!
cascade="all-delete-orphan"
将确保父级保持集合与自己的同步,只要您在更改父级后保存或更新父级,它将invoicePartner
表中相应地插入,更新和删除行。采集!
但是您应该在父inverse="true"
上设置bag
并将inverse="false"
添加到invoicePartner
many-to-one
映射中。完成此操作后,检查我在第3段中提到的情况,其中NHibernate无法识别实体,并确保它确实将invoicePartners
与它们的标识符关联并有效地进行了更改。
参考:http://nhibernate.info/doc/nhibernate-reference/example-parentchild.html