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

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

В онлайн-документации Hibernate в разделе 7.2.3 One-to-many упоминается, что:

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

Я хотел бы знать, почему? Единственное, что приходит мне на ум, это может создать проблемы при каскадном удалении. Например, 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)

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


person Shaw    schedule 19.01.2010    source источник
comment
см. stackoverflow.com/questions/1307203/   -  person Adrien Be    schedule 23.10.2012


Ответы (1)


однонаправленная ассоциация «один ко многим» для внешнего ключа является необычным случаем и не рекомендуется.

В этом есть два аспекта:

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

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

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

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

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

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

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

person APC    schedule 19.01.2010
comment
Спасибо, это многое проясняет! - person Shaw; 20.01.2010
comment
Я не уверен, рекомендуете ли вы однонаправленный «один ко многим» или нет. - person Aravind Yarram; 01.02.2011
comment
Я согласен с @Pangea. APC приводит несколько хороших замечаний, с некоторыми из которых я согласен, но неясно, что APC считает хорошим решением. - person Joshua Davis; 29.06.2012
comment
Что касается однонаправленной ассоциации, то можно работать с ненулевым ограничением! Я использую сопоставления xml и просто требую установить атрибут not-null=true в теге ‹key ›. Я уверен, что есть эквивалент с аннотацией. - person pablo.vix; 22.05.2018