Задача в структуре базы данных устаревшей базы
-
30-09-2019 - |
Вопрос
У меня проблемы с сопоставлением следующей структуры базы данных (сокращен для краткости только с PKS/FK и несколькими дополнительными столбцами:
Политика
Police_id (pk) ...
Риск
Risk_id (PK) ...
Вечеринка
Party_id (pk) ...
Партироль
- Partyrole_id (pk)
- Party_id (fk не null)
- Police_id (fk)
- Risk_id (fk)
- Party_role_type
Таким образом, таблица Partyrole может содержать строку, которая связывает сторону с политикой и/или строкой, которая связывает одну и ту же сторону с риском. По сути, многие для многих присоединяются к таблице, но он сочетает в себе многие со многими отношениями: Party <--> политика и один для партии <--> риска. Party_role_type может быть либо политикой, либо стороной, и действует эффективно как дискриминатор, чтобы определить, к какому отношению относится строка.
Я пытался смоделировать эту структуру с 4 организациями: политика, партия, риск, партия. Вот сопоставления: код:
<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 TABLE: PARTY_ROLE
Что не так? Также это лучший способ сопоставить эти отношения? Есть ли шанс как -то на карту составить эти отношения без Использование промежуточной сущности? Спасибо за всю вашу помощь.
Решение
У меня на самом деле не было возможности вернуться к написанию ответа на это, но я обнаружил, что проблема. Проблема была здесь в этих строках:
<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>
Я тупо упустил, что «столбец», указанный в элементах мешков, указывает на Police_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>
Другие советы
Мне кажется, что это ошибка, сгенерированная вашим RDBMS. Итак, попробуйте включить журнал SQL (hibernate.show_sql = true) и посмотрите, что пытается сделать Hibernate. Но я бы дважды проверил структуру таблицы для Party_Role, так как кажется, что FK были созданы с не-нулевыми ограничениями. Есть некоторые базы данных (Sybase, IIRC), которые по умолчанию создают FK с не-нулевыми. И, если вы указываете отношения как NULL, это может попытаться найти политику с ID NULL, который, безусловно, не будет существовать :-)