旧数据库结构Hibernate映射问题

时间:2010-12-02 14:30:59

标签: hibernate legacy hibernate-mapping hbm legacy-database

我在映射以下数据库结构时遇到问题(为了简洁而缩短了PKs / FK和一些额外的列:

政策

Policy_Id(PK) ...

风险

Risk_Id(PK) ...

Party_Id(PK) ...

成员角色

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

因此,PartyRole表可以包含将一方链接到Policy的行和/或将同一方链接到Risk的行。 基本上它是一个多对多的连接表,但它结合了多对多的关系:Party< - > Policy和一个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保存时,我希望保存与策略关联的各方。当我向策略和风险(以及所有相关角色)添加一个Party时,我得到以下异常:

引起:java.sql.BatchUpdateException:完整性约束违规:外键没有父级; FK_PARTY_ROLE_POLICY表:PARTY_ROLE

有什么问题?这也是映射这种关系的最佳方式吗?有没有机会以某种方式映射这种关系没有使用中间实体?谢谢你的帮助。

2 个答案:

答案 0 :(得分: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”constrant。因此定义最终看起来像这样:

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

答案 1 :(得分:0)

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