2

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

政策

Policy_Id (PK) ...

风险

Risk_Id (PK) ...

聚会

Party_Id (PK) ...

派对角色

  • PartyRole_Id (PK)
  • Party_Id(FK 非空)
  • Policy_Id (FK)
  • Risk_Id (FK)
  • 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

怎么了?这也是映射这种关系的最佳方式吗?是否有机会在使用中间实体的情况下以某种方式映射这种关系?谢谢你的帮助。

4

2 回答 2

1

我真的没有机会回去写一个答案,但我发现了问题所在。问题出在以下几行:

<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>
于 2010-12-07T11:32:23.553 回答
0

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

于 2010-12-03T13:18:53.017 回答