遗留数据库结构Hibernate映射问题

发布于 2024-10-05 10:40:50 字数 3390 浏览 4 评论 0原文

我在映射以下数据库结构时遇到问题(为简洁起见,仅使用 PK/FK 和一些额外的列进行了缩写:

Policy

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_Role_Type 可以是 POLICY 或 PARTY,并且有效地充当鉴别器来识别该行属于哪个关系。

我尝试用 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 pojo 都设置为匹配此映射,并且当在集合中添加或删除对象时,所有关联都会正确设置。策略被认为是聚合根,因此当 Hibernate 保存它时,我想保存与策略相关的各方。当我向策略和风险(以及所有关联的角色)添加一方时,出现以下异常:

Caused by: java.sql.BatchUpdateException:integrityconstraintviolation:foreignkeynoparent; FK_PARTY_ROLE_POLICY 表:PARTY_ROLE

有什么问题?这也是映射这种关系的最佳方式吗?是否有机会在不使用中间实体的情况下以某种方式映射这种关系?感谢您提供的所有帮助。

I am having trouble mapping the following database structure (shortened for brevity with just PKs/FKs and a few extra columns:

Policy

Policy_Id (PK)
...

Risk

Risk_Id (PK)
...

Party

Party_Id (PK)
...

PartyRole

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

So the PartyRole table can contain a row that links a party to a Policy and/or a row that links the same party to a Risk.
Basically it is a many to many join table but it combines both many to many relationships: Party<->Policy and one for Party<->Risk. Party_Role_Type can be either POLICY or PARTY and acts effectively as a discriminator to identify which relationship the row belongs to.

I've tried to model this structure with a 4 entities: Policy, Party, Risk, PartyRole. Here are the mappings:
Code:

<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>

All the java pojos are setup to match this mapping and all associations are setup correctly when objects added or deleted in collections. Policy is considered an aggregate root, so when it is saved by Hibernate I want to save the Parties associated with the Policy. When I add a Party to the Policy and Risk (and all the associated roles) I get the following exception:

Caused by: java.sql.BatchUpdateException: integrity constraint violation: foreign key no parent; FK_PARTY_ROLE_POLICY table: PARTY_ROLE

What is wrong? Also is this the best way to map this relationship? Is there a chance to map this relationship somehow without the use of the intermediate entity? Thanks for all you help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心房的律动 2024-10-12 10:40:50

我真的没有机会重新写下这个问题的答案,但我发现了问题所在。问题就在这里:

<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 并且为了区分策略角色和政党角色,我必须在包上使用“where”约束。所以定义最终看起来像这样:

<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>

I didn't really get a chance to get back to writing an answer to this, but I found what the problem was. The issue was in these lines here:

<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>

I stupidly missed that the "column" specified in the elements of the bags is pointing to Policy_Id and Risk_Id, which is incorrect. It should be the name of the foreign key column that references the primary key of the entity where the one-to-many bags are defined. So in my case it should have been Party_Id and to differentiate between policy roles and party roles, I had to use a "where" constrant on the bag. So the definitions ended up looking like this:

<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>
一袭水袖舞倾城 2024-10-12 10:40:50

在我看来,这是您的 RDBMS 生成的错误。因此,尝试启用 SQL 日志记录 (hibernate.show_sql=true) 并查看 Hibernate 正在尝试执行的操作。但我会仔细检查 PARTY_ROLE 的表结构,因为 FK 似乎是使用非空约束创建的。有一些数据库(Sybase、IIRC)默认创建不为空的 FK。而且,如果您将关系指定为 NULL,它可能会尝试查找 ID 为 NULL 的 POLICY,这肯定不存在:-)

Sounds to me that this is an error generated by your RDBMS. So, try to enable the SQL logging (hibernate.show_sql=true) and see what Hibernate is trying to do. But I would double-check the table structure for PARTY_ROLE, as it seems that the FKs were created with not-null constraints. There are some databases (Sybase, IIRC) that creates the FKs with not-null by default. And, if you specify the relationship as NULL, it may try to find a POLICY with the ID NULL, which certainly won't exist :-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文