Подтвердить что ты не робот

Почему рекомендуется избегать однонаправленной связи "один-ко-многим" с внешним ключом?

Возможный дубликат:
Hibernate однонаправленная связь для многих - почему таблица соединений лучше?

В онлайн-документации Hibernate в разделе 7.2.3 "Один ко многим" он упомянул, что:

однонаправленная связь "один-ко-многим" по иностранному ключу - необычный случай, и не рекомендуется. Вам следует вместо этого используйте таблицу соединений для такого рода ассоциации.

Хотелось бы знать, почему? Единственное, что приходит мне на ум, это может создать проблемы во время каскадных удалений. Например, Person ссылается на адрес от одного до многих отношений по внешнему ключу, и адрес будет отказываться от удаления перед человеком.

Может ли кто-нибудь объяснить рациональность рекомендации?

Вот ссылка на содержание справочного документа: 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)

Вместо этого вы должны использовать таблицу соединений для такой ассоциации.

4b9b3361

Ответ 1

однонаправленная связь "один-ко-многим" по иностранному ключу - необычный случай, и не рекомендуется.

Есть два аспекта:

  • однонаправленный
  • один-ко-многим

thread @CalmStorm удалили ответные ссылки на адреса только второй из этих вещей, но пусть начнется с нее.

Этот поток рекомендует заменять отношения "один ко многим" с таблицами соединений, потому что в противном случае подход "один-ко-многим" заполняет множество боковых таблиц столбцами, которые не принадлежат этому объекту, существуют только для "связывания" поры (так в оригинале). Эта тактика может привести к чистой модели в слое Hibernate, но, к сожалению, это приводит к поломке базы данных.

Поскольку SQL может только утверждать, что у дочерней записи есть родитель; нет способа обеспечить соблюдение правила, согласно которому родитель должен иметь ребенка. Следовательно, нет никаких оснований настаивать на том, что таблица имеет записи в таблице соединений, а это значит, что становится возможным иметь осиротевшие дочерние записи, то, что предназначено для предотвращения внешних ключей.

У меня есть несколько других возражений, но следующая самая важная из них - нецелесообразность. Таблицы пересечений предназначены для представления отношений "многие ко многим". Использование их для представления отношений "один ко многим" сбивает с толку и требует слишком много дополнительных объектов базы данных по своему вкусу.

Итак, во втором аспекте: однонаправленные ассоциации "один ко многим". Проблема заключается в том, что Hibernate обрабатывает их по умолчанию. Если мы вставляем родительский элемент и дочерний объект в одну транзакцию, Hibernate вставляет дочернюю запись, затем он вставляет родительский элемент, а затем обновляет дочерний элемент родительским ключом. Это требует отложенных ограничений внешнего ключа (yuck!) И, вероятно, отложенных и ненулевых ограничений (двойной yuck).

Существует несколько способов обхода. Один из них - использовать двунаправленные ассоциации "один ко многим". Согласно в документе, который вы цитируете, это наиболее распространенный подход. Другой подход состоит в том, чтобы настроить отображение дочернего объекта, но имеет свои собственные ветвления.