映射父子关系——由两个对象的字段组成的复合键

Posted

技术标签:

【中文标题】映射父子关系——由两个对象的字段组成的复合键【英文标题】:Mapping parent child relationship - composite key formed by fields of two objects 【发布时间】:2010-08-26 19:56:11 【问题描述】:

共有三个对象实体:GrandParent、Parent 和 Child

GrandParent 包含 grandParentId Parent 包含对象 GrandParent、parentId、一些属性和 Child 列表。 Child 包含 childId 和一些属性。

有四个表:GrandParent、Parent、Child、ParentsChildrenList

主键为 grandParentId 的 GrandParent 主键为 grandParentId,parentId 的父级 主键为 grandParentId,childId 的孩子 主键为grandParentId,parentId,childId的ParentsChildrenList

Parent 和 Child 都由复合键标识。

应该如何映射这种关系?请注意,对象 Child 不包含对 Parent 或 GrandParant 的引用,但是表 Child 使用 grandParentId 作为其主键的一部分。

此表结构满足用例。但是,映射不是直截了当的。任何设计见解都值得赞赏。

[--- 更新 1 ---]

我将对象 GrandParent 添加到 Child,并创建了复合键 ChildId 以映射到表。问题仍然存在:Child 可以从 Parent 借用其 id 的一部分吗?这样我就不需要纯粹为了持久性而在 Child 中引入 GrandParent。

[--- 更新 2 ---]

我从 Child 中删除了对象 GrandParent,但保留了 ChildId 和允许设置 grandParentId 的方法。事情仍然按预期工作。我怀疑这不能进一步减少。

【问题讨论】:

【参考方案1】:

我得到的最直接的见解是按照 hibernate 的建议,使用代理键。这意味着每个类都有一个 id 仅用于持久性目的。您仍然可以映射自然键。否则你真的是在和框架作斗争,你不会高兴的。

也就是说,我所在的一个团队通过为 id 创建一个自定义类型解决了这个问题,其中一个部分被分配并生成。

这也可能会有所帮助 http://opensource.atlassian.com/projects/hibernate/browse/HHH-2060

【讨论】:

代理键确实让事情变得容易多了。 @candy,是的。您不想与框架抗争。并不是说这是居高临下,而是如果你不得不问如何去做,在这种情况下,你可能无法得到一个好的解决方案。证明我错了或使用 Sks ! ;)【参考方案2】:

为了补充其他帖子所暗示的内容,创建自定义类型可以在定义键时提供更大的灵活性。您还可以使用具有单列的自定义 id 类型,但添加您自己的自定义逻辑以根据构造函数的参数生成代理键。

复合示例:

      (Child ) 
      public class Child implements java.io.Serializable 
         private ChildId id;
             ....
      (ChildId )
      public class ChildId implements java.io.Serializable 
        private long id;
        private long parent_id;
            .....
     (Child.cfg.xml)
          ....
      <composite-id name="id" class="ChildId">
        <key-property name="id" type="long">
            <column name="id" />
        </key-property>
        <key-property name="parent_id" type="long">
            <column name="parent_id" />
        </key-property>
      </composite-id>
         .....

用法:

   Child c = new Child ();
   ChildId cid = new ChildId(null,1);
   c.setId(cid);
   session.save(c);

创建自定义类型允许与 ORM 紧密耦合的大量自定义,而不是在应用程序层中构建解决方案。

【讨论】:

表子是参考grandParentId,而不是parentId。此外, ChildId 应如何使用当前设置填充 parentId?请注意,Child 仅包含其 id 和其他一些普通属性。

以上是关于映射父子关系——由两个对象的字段组成的复合键的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Fluent NHibernate 中将一对一关系映射为复合键的一部分

单向映射——父子实体的复合键

如何修改 PetaPoco 类以使用由非数字列组成的复合键?

ejb3:用简单的主键映射多对多关系

如何在 SQL 中定义复合主键?

Nhibernate一对多关系复合键问题