Когда использовать inverse=false в отношениях NHibernate / Hibernate OneToMany?
Я пытался справиться с обратным атрибутом Hibernate, и это, кажется, только одна из тех вещей, которые концептуально сложны.
суть, которую я получаю, заключается в том, что когда у вас есть родительский объект (например, родитель), который имеет коллекцию дочерних объектов с помощью один-ко-многим сопоставление, установка inverse=true на сопоставлении говорит Hibernate, что " другая сторона (дочерний элемент) несет ответственность за обновление себя для поддержания ссылки на внешний ключ в своем стол".
выполнение этого, по-видимому, имеет 2 преимущества, когда речь заходит о добавлении детей в коллекцию в вашем коде, а затем сохранении родителя (с cascade-all set):вы сохраняете ненужное попадание в базу данных (потому что без обратного набора Hibernate считает, что у него есть два места для обновления отношения FK), и согласно официальным документам:
Если столбец a
ассоциация объявлена
Не NULL, NHibernate может вызвать
ограничение нарушения при его создании
или обновляет ассоциацию. Предотвращать
эта проблема, вы должны использовать
двунаправленная ассоциация с
многие ценят конец (набор или мешок)
помечено как inverse= "true".
все это, кажется, имеет смысл до сих пор. Чего я не понимаю, так это: когда бы вы не хотите использовать inverse=true для отношения "один ко многим"?
3 ответов:
давайте попробуем реальный мир, а вовсе не надуманный пример:
<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 как nullable, потому что акт сохранения sm будет вставлен в таблицу SpyMaster и таблицу Spy, и только после этого он обновит таблицу Spy для установки FK. В этом случае, если бы мы установили inverse = true, FK никогда не обновлялся бы.
несмотря на высокий голос принятый ответ, у меня есть еще один ответ на это.
рассмотрим диаграмму классов с этими отношениями:
Parent => list of Items Item => Parentникто когда-нибудь сказал, что отношение Item => Parent является избыточным для отношения Parent => Items. Элемент может ссылаться на любого родителя.
но в приложении вы знаете, что отношения являются избыточными. Вы знаете, что отношения не должны храниться отдельно в база данных. Поэтому вы решили хранить его в один внешний ключ, указывая от элемента к родителю. Этой минимальной информации достаточно, чтобы построить список и ссылка назад.
все, что вам нужно сделать, чтобы сопоставить это с NH:
- используйте один и тот же внешний ключ для обоих отношений
- скажите NH, что один (список) является избыточным для другого и может быть проигнорирован при хранении объекта. (Это то, что NH на самом деле делает с
inverse="true")это мысли, которые имеют отношение к обратному. Больше ничего. Это не выбор, есть только один способ правильного отображения.
Проблема Шпиона: Это совершенно другая дискуссия если вы хотите поддержать ссылку от элемента родителя. Это зависит от вашей бизнес-модели, NH не принимает никаких решений в этом. Если одно из отношений отсутствует, то, конечно, нет избыточности и нет смысла в обратном.
злоупотребление: если вы используете inverse= "true" в списке, который не имеет избыточности в памяти, он просто не сохраняется. Если вы не укажете inverse= "true", если он должен быть там, NH может хранить избыточную информацию дважды.
Если вы хотите иметь однонаправленную ассоциацию, т. е. что дети не могут перейти к родителю. Если это так, то столбец FK должен быть NULLABLE, потому что дочерние элементы будут сохранены перед родителем.
Comments