Устаревшая структура базы данных Проблема отображения Hibernate - PullRequest
2 голосов
/ 02 декабря 2010

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

Политика

Policy_Id (PK) ...

Риск

Risk_Id (PK) ...

Сторона

Party_Id (PK) ...

PartyRole

  • PartyRole_Id (PK)
  • Party_Id (FK not-null)
  • Policy_Id (FK)
  • Risk_Id (FK)
  • Party_Role_Type

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

Я пытался смоделировать эту структуру с 4 сущностями: Политика, Партия, Риск, 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 pojos настроены для соответствия этому отображению, и все ассоциации настроены правильно, когда объекты добавляются или удаляются в коллекциях. Политика считается совокупным корнем, поэтому при ее сохранении в Hibernate я хочу сохранить стороны, связанные с этой политикой. Когда я добавляю сторону в политику и риск (и все связанные роли), я получаю следующее исключение:

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

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

Ответы [ 2 ]

1 голос
/ 07 декабря 2010

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

<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>
0 голосов
/ 03 декабря 2010

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

...