Почему рекомендуется избегать однонаправленной связи один-ко-многим на внешнем ключе?
Возможный дубликат:
Гибернация однонаправленная связь один ко многим - почему таблица соединений лучше?
В онлайн-документации Hibernate в разделе 7.2.3 "Один ко многим" упоминается, что:
однонаправленная связь "один ко многим" на внешнем ключе является необычным случаем и не рекомендуется. Вместо этого вы должны использовать таблицу соединений для такого рода ассоциации.
Я хотел бы знать, почему? Единственное, что приходит мне в голову - это может создавать проблемы при каскадном удалении. Например, Персона относится к адресу в отношении "один ко многим" по внешнему ключу, и этот адрес будет отклонен до удаления этого лица.
Кто-нибудь может объяснить рациональное обоснование рекомендации?
Вот ссылка на содержание справочного документа: 7.2.3. Один ко многим
Я скопировал вставленный фактический контент здесь:
Однонаправленная связь "один ко многим" на внешнем ключе является необычным случаем и не рекомендуется.
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <set name="addresses"> <key column="personId" not-null="true"/> <one-to-many class="Address"/> </set> </class> <class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> </class>
create table Person (personId bigint not null primary key) create table Address (addressId bigint not null primary key, personId bigint not null)
Вместо этого вы должны использовать таблицу соединений для такого рода ассоциации.
1 ответ
однонаправленная связь "один ко многим" на внешнем ключе является необычным случаем и не рекомендуется.
Есть два аспекта этого:
- однонаправленный
- один ко многим
Удаленный ответ ветки @CalmStorm ссылается на адреса только второй из этих вещей, но давайте начнем с этого.
Этот поток рекомендует заменять отношения "один ко многим" таблицами соединения, потому что в противном случае подход "один ко многим" заполняет таблицу многих сторон столбцами, которые не принадлежат этой сущности, они предназначены только для "связывания" частей (sic) ". Эта тактика может привести к чистой модели в слое Hibernate, но, к сожалению, это приведет к повреждению базы данных.
Поскольку SQL может только утверждать, что у дочерней записи есть родительский элемент; нет способа обеспечить соблюдение правила, согласно которому родитель должен иметь ребенка. Следовательно, нет никакого способа настаивать на том, чтобы в таблице были записи в объединяемой таблице, в результате становится возможным иметь потерянные дочерние записи, то есть то, что внешние ключи предназначены для предотвращения.
У меня есть несколько других возражений, но следующим по важности является неуместность. Таблицы пересечений предназначены для представления отношений "многие ко многим". Использование их для представления отношений "один ко многим" сбивает с толку и требует слишком много дополнительных объектов базы данных на мой взгляд.
Итак, ко второму аспекту: однонаправленные ассоциации "один ко многим". Проблема в том, что Hibernate обрабатывает их по умолчанию. Если мы вставим родительский и дочерний элементы в одну транзакцию, Hibernate вставит дочернюю запись, затем вставит родительский элемент, а затем обновит дочерний элемент с помощью ключа родительского элемента. Это требует откладываемых ограничений внешнего ключа (хм!) И, вероятно, также откладываемых ограничений, не равных нулю (двойной гадость).
Есть несколько способов обойти это. Одним из них является использование двунаправленных ассоциаций "один ко многим". Согласно приведенному вами документу, это наиболее распространенный подход. Другой подход состоит в том, чтобы настроить отображение дочернего объекта, но у этого есть свои собственные последствия.