Устаревшая структура базы данных Проблема сопоставления Hibernate

У меня возникли проблемы с отображением следующей структуры базы данных (сокращенной для краткости только с PK/FK и несколькими дополнительными столбцами:

Политика

Идентификатор_политики (ПК) ...

Риск

Risk_Id (ПК) ...

Вечеринка

Party_Id (ПК) ...

PartyRole

  • PartyRole_Id (ПК)
  • Party_Id (FK не нулевой)
  • Идентификатор политики (FK)
  • Risk_Id (ФК)
  • Party_Role_Type

Таким образом, таблица PartyRole может содержать строку, связывающую сторону с политикой, и/или строку, связывающую ту же сторону с риском. По сути, это таблица соединения «многие ко многим», но она сочетает в себе отношения «многие ко многим»: Party‹->Policy и один для Party‹->Risk. Party_Role_Type может быть либо POLICY, либо PARTY и эффективно действует как дискриминатор, чтобы определить, к какой связи принадлежит строка.

Я попытался смоделировать эту структуру с помощью 4 объектов: Policy, Party, Risk, PartyRole. Вот сопоставления: Код:

<class name="com.blah.Party" table="Party">

    <id column="Party_Id" name="_id" type="int" unsaved-value="-1" access="field">
      <generator class="sequence">
        <param name="sequence">SQ_Party</param>
      </generator>
    </id>

    <bag name="_policyRoles" access="field" table="Party_Role">
      <key column="Policy_Id" />
      <one-to-many class="com.blah.PartyRole" />
    </bag>

    <bag name="_riskRoles" access="field" table="Party_Role">
      <key column="Risk_Id" />
      <one-to-many class="com.blah.PartyRole" />
    </bag>

  </class>

  <class name="com.blah.Risk" table="Risk">

    <id column="Risk_Id" name="_id" type="int" unsaved-value="-1" access="field">
      <generator class="sequence">
        <param name="sequence">SQ_Risk</param>
      </generator>
    </id>

    <bag name="_partyRoles" access="field">
      <key column="Risk_Id" />
      <one-to-many class="com.blah.PartyRole" />
    </bag>

  </class>

  <class name="com.blah.Policy" table="Policy">

    <id column="Policy_Id" name="_id" type="int" unsaved-value="-1" access="field">
      <generator class="sequence">
        <param name="sequence">SQ_Policy</param>
      </generator>
    </id>

    <bag name="_partyRoles" inverse="true" cascade="save-update" access="field" table="Party_Role" >
      <key column="Policy_Id" />
      <one-to-many class="au.com.cgu.harvest.domain.party.PartyRole" />
    </bag>

  </class>

<class name="au.com.cgu.harvest.domain.party.PartyRole" table="Party_Role" schema="Harvest">

    <id column="Party_Role_Id" name="_id" type="int" unsaved-value="-1" access="field">
      <generator class="sequence">
        <param name="sequence">Harvest.SQ_Party_Role</param>
      </generator>
    </id>

    <property name="partyRoleType" column="PARTY_ROLE_TYPE"
      type="java.lang.String" />

    <many-to-one name="_party" column="Party_Id" class="com.blah.Party" access="field" cascade="save-update" fetch="join" />

    <many-to-one name="_risk" column="Risk_Id" class="com.blah.Risk" access="field" />

    <many-to-one name="_policy" column="Policy_Id" class="com.blah.Policy" access="field" />

  </class>

Все java pojo настроены в соответствии с этим сопоставлением, и все ассоциации настроены правильно, когда объекты добавляются или удаляются в коллекциях. Политика считается совокупным корнем, поэтому, когда она сохраняется в Hibernate, я хочу сохранить Стороны, связанные с Политикой. Когда я добавляю Сторону в Политику и Риск (и все связанные роли), я получаю следующее исключение:

Вызвано: java.sql.BatchUpdateException: нарушение ограничения целостности: внешний ключ не имеет родителя; Таблица FK_PARTY_ROLE_POLICY: PARTY_ROLE

Что не так? Кроме того, это лучший способ отобразить эти отношения? Есть ли возможность каким-то образом сопоставить эту связь без использования промежуточного объекта? Спасибо за все, что вы помогаете.


person Strelok    schedule 02.12.2010    source источник


Ответы (2)


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

<bag name="_policyRoles" access="field" table="Party_Role">
  <key column="Policy_Id" />
  <one-to-many class="com.blah.PartyRole" />
</bag>

<bag name="_riskRoles" access="field" table="Party_Role">
  <key column="Risk_Id" />
  <one-to-many class="com.blah.PartyRole" />
</bag>

Я тупо упустил, что указанная в элементах мешков "колонка" указывает на Policy_Id и Risk_Id, что неверно. Это должно быть имя столбца внешний ключ, который ссылается на первичный ключ объекта, в котором определены пакеты "один ко многим". Таким образом, в моем случае это должен был быть Party_Id, и чтобы различать роли политики и роли партии, мне пришлось использовать константу «где» на сумке. Таким образом, определения в конечном итоге выглядели так:

<bag name="_policyRoles" access="field" table="Party_Role" where="Party_Role_Type = 'POLICY'">
  <key column="Party_Id" />
  <one-to-many class="com.blah.PartyRole" />
</bag>

<bag name="_riskRoles" access="field" table="Party_Role" where="Party_Role_Type = 'RISK'">
  <key column="Party_Id" />
  <one-to-many class="com.blah.PartyRole" />
</bag>
person Strelok    schedule 07.12.2010

Мне кажется, что это ошибка, сгенерированная вашей СУБД. Итак, попробуйте включить ведение журнала SQL (hibernate.show_sql=true) и посмотреть, что пытается сделать Hibernate. Но я бы перепроверил структуру таблицы для PARTY_ROLE, так как кажется, что FK были созданы с ненулевыми ограничениями. Есть некоторые базы данных (Sybase, IIRC), которые по умолчанию создают FK с ненулевым значением. И, если вы укажете отношение как NULL, он может попытаться найти ПОЛИТИКУ с ID NULL, которого точно не будет :-)

person jpkrohling    schedule 03.12.2010