兔八哥笔记15(1):Hibernate中的父子关系

类别:Java 点击:0 评论:0 推荐:

兔八哥笔记15:Hibernate中的父子关系

          邮箱:[email protected]

 

       本文翻译自Hibernate帮助文档的第九章。

Hibernate的新用户用Hibernate做的第一件事情很可能就是建立一个父子关系的数据模型。要达到这个目的,有2种途径:由于有不同的情况,最方便(特别是对于一个Hibernate的新用户来说)的途径是同时建立2个实体,一个是Parent,另一个是Child,然后建立一个从Parent到Child的<one-to-many>关联。另外一个途径是生命Child作为Parent的<composite-element>。Now, it turns out that default semantics of a one to many association (in Hibernate) are much less close to the usual semantics of a parent / child relationship than those of a composite element mapping.(这句没太读明白)。下面我们将向你展示怎样使用bidirectional one to many association with cascades去建立一个优雅且有效率的父子关系的模型,一点都不难!

 

9.1 关于集合的小结(A note about collections)

       Hibernate集合被认为是实体自己的一个逻辑部分,而不是被包含的实体。这个区别是至关重要的!

       当我们从一个集合中增加或删除一个对象时,集合所有者的版本号将会增加。

       如果从集合中被删除的对象是一个值类型的实例(eg, a composite element),对象将不再是持久的,它的状态将从数据库中完全删除。同样,向集合中增加一个值类型的实例时,将会使它的状态立刻被持久化。

       另一方面,如果一个实体从一个集合(a one-to-many or many-to-many association),中被removed,默认情况下,关联的实体将不被删除(deleted)。这个行为同下面的说法是完全一致的:其他实体的内部状态的改变不应该引起相关联的实体的消失(vanish)!同样,向集合中增加一个实体,在默认情况下,不会引起实体被持久化。

       所以,向集合中增加一个实体时,仅仅是创建了一个两个实体之间的连接(link),而删除时,也仅仅删除了连接(link),这个规则适合各种各样的(all sorts of)情况。但也有根本不适合的情况:在父子关系中,Child的生命被绑定到Parent对象的生命期(lifecycle)中。

      

9.2 双向的one-to-many(Bidirectional one to many)

       假设我们有一个简单的从Parent到Child对象的<one-to-many>关联:

<set name="children">

      <key column="parent_id"/>

      <one-to-many class="Child"/>

</set>

    如果我们要执行下面的代码:

Parent p = .....;

Child c = new Child();

p.getChildren().add(c);

session.save(c);

session.flush();

Hibernate将转换成2个SQL语句:

²        一条为创建Child的insert语句

²        一条创建Parent到Child的关系的update语句

这样做不仅效率低下,而且违反了parent_id列的NOT NULL约束。

下面的动机是:从Parent到Child的连接(外键:parent_id)没有被作为Child的状态的部分被考虑,所以在Insert中没有被创建。所以,我们将建立Child映射部分的连接:

<many-to-one name="parent" column="parent_id" not-null="true"/>

       我们也需要为Child类增加parent属性。

       现在Child实体被作为连接的状态被管理,我们使用inverse告诉集合不要去更改连接。

     <set name="children" inverse="true">

          <key column="parent_id"/>

        <one-to-many class="Child"/>

   </set>

   下面的代码将添加一个新的Child:

Parent p = (Parent) session.load(Parent.class, pid);

Child c = new Child();

c.setParent(p);

p.getChildren().add(c);

session.save(c);

session.flush();

现在,只有一个Insert语句被执行!

       下面我们为Parent添加一个addChild()方法:

public void addChild(Child c) {

    c.setParent(this);

    children.add(c);

}

现在,添加一个Child的代码应该看起来像这样:

Parent p = (Parent) session.load(Parent.class, pid);

Child c = new Child();

p.addChild(c);

session.save(c);

session.flush();

本文地址:http://com.8s8s.com/it/it16838.htm