重温Hibernate级联(转)

     本人乃普通人一个,放到人群中是找不到的那种,不比那些牛人能过目不忘,我相信那句话——书读百遍,其义自显,所以一本书我一般都读好几遍,第一遍一般都是概读,达到初步掌握,能使用的地步,以后再一遍又一遍的精读,以便能够加深理解,从中得到新的体会。可以说级联是Hibernate的一大亮点,也是比较麻烦的地方。下面就是我的读书记录,以及个人体会。

双向一对多父子关系

保存子

Parent p=(Parent)session.load(Parent.class.pid);
Child c=new Child();
c.setParent(p);
p.getChildren().add(c);
session.save(c);
session.flush():
为Parent添加一个addChild()方法
public void addChild(Child c){
c.setParent(this);
children.add(c);
}
这样上面的就可以替换为:
Parent p=(Parent)session.load(Parent.class.pid);
Child c=new Child();
p.addChild(c);
session.save(c);
session.flush():
以上是没有使用cascade参数,要是使用cascade参数,如cascade="all",以上简化为:
Parent p=(Parent)session.load(Parent.class.pid);
Child c=new Child();
p.addChild(c);
session.flush():
注意这里不用显式调用save方法了,同样的,保存或删除Parent对象的时候并不需要遍历其子对象,下面的代码会删除对象
p及其所有子对象对应的数据库记录。
Parent p=(Parent)session.load(Parent.class,pid);
session.delete(p);
session.flush();
然而,这段代码如下
Parent p=(Parent)session.load(Parent.class,pid);
Child c=(Child)p.getChildren().iterator().next();
p.getChildren().remove(c);
c.setParent(null);
session.flush();
不会从数据库删除c;它只会删除与p之间的连接(并且会导致违反NOT NULL约束,在这个例子中)。你要显式调用delete()来
删除Child。
Parent p=(Parent)session.load(Parent.class.pid);
Child c=(Child)p.getChildren().iterator().next();
p.getChildren.remove(c);
session.delete(c);
session.flush();

在我们的例子中,如果没有父对象,子对象就不应该存在,如果将子对象从Colletction中移除,实际上我们是想删除它。

要实现这种要求,就必须使用cascade="all-delete-orphen"。

注意:即使在Collection一方的映射中指定inverse="true",级联仍然是通过遍历Collection中的元素来处理的。如果你想

通过级联进行子对象的插入、删除、更新操作,就必须把它加载到Collection中,只调用setParent()是不够的。
当级联更新时,对象Parent包含了子对象的集合,由于打开了级联更新,Hibernate需要知道哪些Child对象是新实例化的,哪
些代表数据库中的记录。我们假设Parent和Child对象的标识符都是自动分配的,Hibernate是通过对象的标示属性的值和
version或timestamp属性来判断哪些子对象是新的。下面代码会更新Parent和child对象,并且插入newChild对象。

//parentandchildwherebothloadedinaprevioussession

parent.addChild(child);//把父关联的子上,把子关联到父上.

ChildnewChild=newChild();

parent.addChild(newChild);

session.update(parent);

session.flush();

这对于自动分配标识符的情况是非常好的,但是要是自定义的,即id的子元素<generator class="assigned" />,这就比较麻
烦了,因为Hibernate没办法区分新实例化的对象(标识被用户指定了)和前一个Session装入的对象,在这种情况下,
Hibernate会使用timestamp或version属性,或者查询第二级缓存,或者使用最坏的情况,查询数据库,来确认是否存在此
行记录。
个人总结:级联保存、删除,父类只加载自己就行了;但级联更新,父类要加载子类对象,这样它才好区分哪些对象是新实
例的,那些是需要更新的。

级联更新:第一次是保存,以后是更新,则

Parentp=(Parent)session.getCascade(Parent.class,pid);

if(p.getChildren().size()>0){

for(Iteratoriter=p.getChildren().iterator();iter.hasNext();){

//若更新对象

Childc=(Child)iter.next();

c.setName("c");//获取子类信息
parent.addChild(child);//把父关联的子上,把子关联到父上.

}

}else{

Child c=new Child();
…… ……… …… ………
parent.addChild(child);//把父关联的子上,把子关联到父上.

}

相关推荐