Множественные отношения с одной таблицей сопоставления без генерации внешних ключей Hibernate

У меня есть два базовых абстрактных класса, и есть несколько дополнительных классов, производных от этих двух, добавляющих дополнительные атрибуты и т. д.

Между этими конкретными производными типами существуют отношения.

Простой иллюстрирующий пример:

Классы Role и Group относятся к классам abstract, но не помечены как @MappedSuperclass.

Используется стратегия InheritanceType.JOINED, поэтому должны существовать обе таблицы Role (для абстрактного класса) и AdminRole (для производного класса) (они обе будут иметь одинаковые RoleID).

  • DiscussionGroup имеет одно свойство AdminRole, Set<DiscussantRole>, Set<ManagerRole>
  • WorkingGroup есть Set<WorkerRole>, Set<ManagerRole>
Role 
|-- AdminRole
|-- DiscussantRole
|-- ManagerRole
|-- WorkerRole

Group
|-- DiscussionGroup
|-- WorkingGroup

Поскольку количество производных классов может расти, и поскольку классы, производные от роли, могут иметь отношения к другим классам, производным от группы (и наоборот), это может привести к большому количеству различных таблиц сопоставления (Worker_DiscussionGroup, Worker_WorkingGroup) или множеству столбцов внешнего ключа. (в отношениях M:1 — например, роль ManagerRole должна иметь DiscussionGroupID и WorkingGroupId). Я хочу сопоставить все эти отношения с помощью одной общей таблицы сопоставления.

Role_Group (RoleID, GroupId)

Мы используем Hibernate для создания схемы DDL (hbm2ddl.auto=create) во время текущей разработки (мы будем использовать определение статической схемы для дальнейшего использования в рабочей среде). Hibernate автоматически создает внешние ключи для отношений, и это очень хорошо для нас.

Если я укажу ему использовать одно и то же сопоставление таблицы для соединений (многие ко многим, многие ко многим, а также один к одному), он попытается создать внешние ключи тоже. И, конечно же, невозможно создать внешний ключ на RoleID от Role_Group до AdminRole и DiscussantRole одновременно, поэтому я получаю сообщение об ошибке.

Есть ли способ настроить Hibernate

  1. для создания выбранных отношений без внешних ключей

    or

  2. определить, что отношение должно быть основано на абстрактных предках (т. е. группа обсуждения и ее набор должны отображаться как 1:N — группа и набор)?


person devmake    schedule 05.09.2011    source источник


Ответы (2)


Следующее работает для меня как ответ на вопрос номер 2:

@ForeignKey( name = "none" )

Внешний ключ для связи не создается.

@Cascade( value = { CascadeType.ALL } )
@OneToOne( fetch = FetchType.EAGER, orphanRemoval = true )
@JoinTable( name = "Role_Group",
            inverseJoinColumns = { @JoinColumn( referencedColumnName = "rolleId", name = "RolleID" ) },
            joinColumns = { @JoinColumn( referencedColumnName = "groupId", name = "GroupID" ) } )

@ForeignKey( name = "none" )
public AdminRole getAdmin()

Источники:

Судя по источникам, это недокументированная функция, которая была замечена в примечаниях к выпуску:

Changes in version 2.1.9 (xx.x.xxxx)
------------------------------------
* TimesTenDialect now supported (look at TimesTenDialect for certain limitations)
* foreign-key="none" can be used to disable generation of a foreign key.

В конфигурации xml - вы бы использовали это так

<many-to-one name="Hospital" column="hospitalId" property-ref="hospitalId" update="false" insert="false" foreign-key="none">

как указано в Позвольте Hibernate соединить ваш мир! ( смотрите исходники страницы - конфигурация xml не отображается на странице)

Примечание.

Однако это не решает всей проблемы. Hibernate не может получить правильные данные через эту таблицу сопоставления для getAdmin и getManagers, потому что он ищет Role_Group, находит RoleIDs для DiscussionGroup GroupID и понятия не имеет, для AdminRole или ManagerRole и выдает "Нет строки с заданным идентификатор существует" ошибка".

Однако аналогичное сопоставление работает, когда я использую такую ​​​​таблицу в группе или группе обсуждения как public Set<Role> getRoles(), Hibernate успешно загрузит производные классы (AdminRole, ManagerRole) в набор.

person devmake    schedule 06.09.2011

Я думаю, что вы должны держать несколько таблиц. Он просто отображает отношения, существующие в ваших классах.

Если вы этого не хотите, вы можете определить Set<Role> внутри абстрактного Group и Set<Group> в абстрактном Role. У вас не будет никаких «подмножеств» в подклассах; вы просто заполняете набор из абстрактного класса соответствующими элементами нужного типа. Затем автоматическое сопоставление даст вам единую таблицу соединений, как вы хотите.

person toto2    schedule 06.09.2011