Несколько связей с одной таблицей сопоставления без создания внешних ключей с помощью Hibernate - PullRequest
1 голос
/ 06 сентября 2011

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

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

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

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

Поскольку число производных классов может увеличиваться и поскольку классы, производные от Role, могут иметь отношения к различным классам, производным от Group (и наоборот), это приведет к большому количеству различных таблиц сопоставления (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. для генерации выбранных отношений без внешних ключей

    или

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

Ответы [ 2 ]

3 голосов
/ 06 сентября 2011

Следующее работает для меня как ответ на вопрос № 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 и выдает " Строка с указанным идентификатором не существует" error".

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

1 голос
/ 06 сентября 2011

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

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

...