2010-12-01 92 views
2

我正在使用將字段映射到對象的多對多映射表。NHibernate - 將對象添加到多對多集合時,現有對象被刪除並重新插入

相關DB結構...

對象:表
(PK)的ObjectID
[其餘部分是無關緊要]

字段:表
(PK)fieldId
[其餘的是無關]

ObjectFields:表
(pk)fieldObjectid ( FK)fkObjectId - >對象 (FK)fkFieldId - >字段

我的映射是這樣的:

<bag name="Fields" table="ObjectFields" lazy="true" cascade="all"> 
    <key column="fkObjectId"/> 
    <many-to-many class="Field" column="fkFieldId" /> 
</bag> 

現在,所有收集操作工作,你所期望的 - 檢索,添加和刪除。但是,發生了一件非常奇怪的事情。如果我添加一個對象到「Fields」集合中,NHibernate會刪除已經存在的內容並重新插入它。

這裏是我的log4net的轉儲: DEBUG NHibernate.SQL [(NULL)] - 選擇this_.objectId爲objectId6_0_,this_.Name爲Name6_0_,this_.Description爲Descript3_6_0_,this_.RootElement爲RootElem4_6_0_,this_.ChildElement作爲ChildEle5_6_0_,this_.ImageUrl as ImageUrl6_0_,this_.hasChildren as hasChild7_6_0_,this_.CreateStamp as CreateSt8_6_0_ FROM Objects this_ WHERE this_.objectId = @ p0; @ p0 = 5 [Type:Int32(0)]
DEBUG NHibernate.SQL [(選擇fields0_.fkObjectId作爲fkObjectId1_,fields0_.fkFieldId作爲fkFieldId1_,inventoryf1_.fieldId作爲fieldId4_0_,inventoryf1_.fieldName作爲fieldName4_0_,inventoryf1_.fieldType作爲fieldType4_0_,inventoryf1_.fieldType作爲fieldType4_0_,inventoryf1_.Required作爲必需4_0_ FROM ObjectFields fields0_左外部連接字段inventoryf1_關於fields0_ .fkFieldId = inventoryf1_.fieldId WH ERE [email protected]; @ p0 = 5 [Type:Int32(0)]
DEBUG NHibernate.SQL [(null)] - 選擇this_.fieldId作爲fieldId4_0_,this_.fieldName作爲fieldName4_0_,this_.fieldType作爲fieldType4_0_ ,this_.Required as Required4_0_ FROM Fields this_ WHERE this_.fieldId = @ p0; @ p0 = 2 [Type:Int32(0)]
DEBUG NHibernate.SQL [(null)] - DELETE FROM ObjectFields WHERE fkObjectId = @ p0; @p0 = 5 [Type:Int32(0)]
DEBUG NHibernate.SQL [(null)] - INSERT INTO ObjectFields(fkObjectId,fkFieldId)VALUES(@ p0,@ p1); @ p0 = 5 [類型:Int32 0)],@ p1 = 1 [Type:Int32(0)]
DEBUG NHibernate.SQL [(null)] - INSERT INTO ObjectFields(fkObjectId,fkFieldId)VALUES(@ p0,@ p1); @ p0 = 5 [類型:Int32(0)],@ p1 = 2 [類型:Int32(0)]

正如您所看到的,它發出刪除語句,然後重新插入。

任何想法如何防止這種情況?

回答

4

總之,包的行爲就像那樣,你應該使用另一種類型的集合。在這裏,你必須從NHibernate的文檔了很好的解釋,但我remomend你閱讀全篇(17.5. Understanding Collection performance

所有的有序集合(地圖,列表,數組)都擁有一個由和索引列的主鍵。在這種情況下,集合更新通常是非常有效的 - 當NHibernate嘗試更新或刪除它時,主鍵可以被有效地索引,並且可以有效地定位特定的行。

集合具有由鍵和元素列組成的主鍵。對於某些類型的集合元素,這可能效率較低,特別是複合元素或大型文本或二進制字段;數據庫可能無法有效地索引複雜的主鍵。另一方面,對於一對多或多對多的關聯,特別是在綜合標識符的情況下,它可能同樣有效。 (注意:如果您希望SchemaExport實際爲您創建集合的主鍵,則必須將所有列聲明爲not-null =「true」。)

idbag映射定義代理鍵,因此它們是總是非常有效地更新。事實上,他們是最好的例子。

手提袋是最壞的情況。由於一個包允許重複的元素值並且沒有索引列,因此不能定義主鍵。 NHibernate無法區分重複的行。 NHibernate通過徹底刪除(在單個DELETE中)並在集合發生更改時重新創建集合來解決此問題。這可能是非常低效的。

+0

感謝克勞迪奧 - 有道理。那麼問題是,我的映射表有一個主鍵;我怎麼把這個聯繫起來?這與我的課程完全無關,並且實際上「商業邏輯」不需要知道它。 Hibernate可以自動處理它嗎? – Sam 2010-12-01 14:25:15

0

我發現了一個ID包在我的處境更好地工作對我來說,但是從克勞迪奧對方的回答是好。

相關問題