我在映射以下数据库结构时遇到问题(为了简洁而缩短了PKs / FK和一些额外的列:
Policy_Id(PK) ...
Risk_Id(PK) ...
Party_Id(PK) ...
因此,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
有什么问题?这也是映射这种关系的最佳方式吗?有没有机会以某种方式映射这种关系没有使用中间实体?谢谢你的帮助。
答案 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,这当然不会存在:-)