一对多双向关联及inverse和cascade属性

单向多对一关联映射:many-to-one:
1、 所谓的关联就是对象和对象之间在某段时间范围内(是可以持续一段时间的),存在有联系,即关联可以在一开始不存在,后来才建立起来,然后还可以取消和改变如:通过对象A.setB(对象B)建立或更新关联--通过A.setB(null)取消关联
2、 判断关联的多重性:首先站在任何一端的某一个对象的角度判断跟对方那端的多少个对象有联系,如果只有一个的话那么就可以确定对方的多重性是1,如果从对方看我这端有多个的话,那么就确定了这两个对象关联的多重性-----------多对一或者一对多。因此多重性是要双方都确定了对方才能决定关联的多重性
3、 由上可知,关联有双向和单向之分,从A能访问到B,或许从B也能访问到A
4、 将内存中的关联信息,存储到数据库;从数据库中取出数据,并在内存中重建关联
5、 先看单向的多对一关联:<many-to-one name="group" column="groupId"/>其中的name指的是这个与对象Person关联的对象——Group,一般是Person实体中的一个属性,持有对Group的引用,一般情况下,在数据库中的字段名可改成上面的groupId,表明他与Group的联系,因此column是作这个用的
6、 一般先有“一”,然后再有“多”,从“多”一端,建立和“一”之间的关联;这样可以避免先建立多再一的情况下而发出的多余的update语句。就像平常我们的QQ一样也是先有群,然后群下有一堆人
7、 多对一关联映射的RUD重建关联:
8、 关联的重建:Person cp1 = (Person)session.load(Person.class, 1); cp1.getGroup().getName();关联已经被重新建立起来,所以可以直接导航到对应的Group对象,发出了两条sql查询语句分别查询Person及其关联的对象Group
9、 关联的更新:可以像先前那样先load上来然后再update这个关联的Group;也可以这样->直接new出关联对象Group,然后改变Person的group引用,当然这个Group只要设置上id就行了,因为更新的是Person对象而不是Group,所以这是可以的,也是我们平时常用的方式。关联的删除一开始讲了很简单:p.setGroup(null)
单向一对多关联映射one-to-many:
1、 要注意到一对多关联其实也就是多对一的关联,映射的时候是由一的端指向多的一端并在多的一端加个关联标识去维护他,因此一对多和多对一的数据库表结构是完全一样的,只不过配置上会有些不同
<set name="persons"><key column="groupId"></key>
<one-to-many class="cn.com.leadfar.hibernate3.ContactPerson"/>
</set>
2、 属性name跟上面是一样的,指的是对关联的对象的引用;跟多对一一样也要在多的一端增加个字段去维护这个关联关系,这是<key>就是干这个的其column属性表示的是在对方那张表里面增加一个字段(也就是person这张表),然后指定对方是谁:使用one-to-many中的class说明对方是谁
3、 一对多单向关联的维护:保存时主要对集合的使用,这时update语句就去不掉了,因为多的一端没有维护他们之间关联的属性,但他却在数据库中多的一端加入了一个字段维护了,因此一对多单向关联是很少见的;
Group g = (Group)session.load(Group.class, 2);
Person cp = (Person)session.load(ContactPerson.class, 3);
g.getPersons().add(cp);
对集合操作要特别小心:在组下添加人时,可能会陷入下面的误区;
Set<ContactPerson> cps = new HashSet<ContactPerson>();
cps.add(cp);
g.setPersons(cps);
这样会把原来已有的关联的其他记录给置空了
4、 删除关联:
Group g = (Group)session.load(Group.class, 2);
//清空集合,会导致关联关系被删除
g.getPersons().clear();
其实他们两个对象都没删除掉,只是其关联被删除了
5、 集合上的lazy:true|false|extra
Lazy=extr是一种比较聪明的懒加载策略,比如在取集合中有多少个对象或是否包含有某个对象的时候,会发出智能语句,如:count(id)
select 1 from t_person where groupId =? and id =?包含
一对多的双向关联:
1、 注意配置时,多对一的column要与一对多中key的column要保持一致,他们都是共同维护关联的字段或属性,可以从任意一端去维护他们之间的关系,强烈建议在多的一端维护关联关系
2、 当更新一离线对象时,会出现更新一端引起的多端关联关系的丢失,因为一端的引用到的多端是空的,但如果是持久化对象的话,则关联维护着不会丢失;虽然上面load持久化不会丢失关联,但这用在典型的多层架构中是不太现实的,比如Struts2中用ModelDriven更新Group,Group里边有20个属性,先传个id到后台,加载一个Group到页面并呈现出这20个属性来,在jsp界面改变某些属性然后提交给Action,从页面里面传递到Action中的Group是没有集合的数据的,如果你把这个Group对象当做Model的话,从页面里面递交的参数它改的只是Group而已,而他的那些关联我们可能不希望改变它,那么这时候就需要在后台先load下,然后再改变非关联的属性,只能这样改,这会给我们带来很大的麻烦
3、
因此最常见的是更新离线对象,为了不让关联丢失,可以设置集合上的inverse属性,以维持关联关系,让多的一端维护关联关系。下面就不会出现关联丢失了
//更新Group对象
Group g = new Group();
g.setId(2);
g.setName("敌人");
4、 inverse属性:在双向关联中表示由谁来维护表与表之间的关系,由对方维护设置inverse=true,在单向关联中没有这种说法。
级联cascade:
1、 持久化对象是不能引用到瞬时对象的,但他可以引用到离线的对象,所谓离线的对象就是有数据库标识的id对象而瞬时对象却没有这个标识,这有点区别的。比如在关联保存对象时不小心引用到瞬时对象的话就会抛出TransientObjectException异常
如上面的g就是个瞬时的对象,而cp在save操作后会变成持久化对象的,但他发现他的引用Group是瞬时的,则抛出上面的异常,如果给Group设个id标识,则能同步到数据库中去
2、 解决上述的问题,就要引入到Hibernate中的一个重要属性cascade属性,一般选择all,这样的话CUD操作就会将持久化对象和引用到的瞬时对象同步到数据库中,上面的保存也就没有问题
3、 删除操作:删除某一端某条记录的话,同时会把与它相关联的那端的那条记录也删掉,但这是有风险的,万一关联的那端还有其他对象引用的话,会抛出外键关联约束的异常。Person p = (Person)session.load(Person.class, 3);然后执行session.delete(p);注意发出两条delete语句
4、 删除操作:删除一个离线对象即new一个Person然后set它的Id为3吧,然后执行delete操作,这是只发出一条删除该Person的操作,并没有把他的级联的对象Group里面的那条记录给删除掉。因为delete操作不是个持久化对象,因此他就不可能知道他的关联对象,因此也就不能删除它的关联对象,这是cascade就失效了

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值