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

王朝java/jsp·作者佚名  2006-01-08
宽屏版  字体: |||超大  

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

邮箱:ltf_ty@163.net

本文翻译自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();

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
© 2005- 王朝网络 版权所有