在Hibernate中,在对象和对象间存在下面几种关系:一对一,一对多,多对一和多对多,一对一比较简单,这里我不讲了,今天主要谈谈父子关系和多对多的关系
先谈谈父子关系.假设我们有一个简单的从Parent到Child对象的<one-to-many>关联:
<set name="children">
<key column="parent_id"/>
<one-to-many class="Child"/>
</set>
建立了上面的映射,我们可以在编写下面的代码来实现
Parent p=newParent();
Child c=newChild();
p.getChileren().add(c);
session.save(p);
session.flush();
我们来分析下到底Hibernate为我们做了什么
首先创建Insert语句来生成Child记录
然后通过update来更新parent到child之间的关系
但是我们仔细分析发现这里面存在一个很大问题,问题出在insert一个child时候,这时把child记录中的parent_id设置为null,原因在于这个时候还没有建立parent和child之间的关系,parent_id无法确定,如果在我们定义的child表中对parent_id不允许null,那程序执行将会出错.对于这个问题的解决,简单的办法是将child表中的parent_id设置为允许null,但这不是一个好的设计,而且可能对系统的执行效率带来影响.我们这里换种解决办法,建立child到parent的多对一的连接,因而我们在child.hbm.xml中加上下面一句
<many-to-onename="parent"column="parent_id"not-null="true"/>
但需要注意,因为先前在child.hbm.xml中我们已经定义了到字段parent_id的关联,因此要把前面对字段parent_id定义的关联删除,否侧会造成重复定义,还有一点,需要修改下parent.hbm.xml
<setname="children"inverse="true">
<keycolumn="parent_id"/>
<one-to-manyclass="Child"/>
</set>
这里增加inverse="true",因为系统缺省inverse="false",inverse="true"的作用是将parent变成被调用方,从而告诉系统不用去更改连接,连接由child来完成,下面是JAVA代码实现
Parent p=new Parent();
Child c=newChild();
c.setParent(p);
p.getChileren().add(c);
session.save(p);
session.flush();
接下来我们谈谈多对多的关系,这种关系用的不多,原因在于需要额外生成表来维护这种关系,并且会造成对对象的反复查询,这里我们以role和group为例,一个role可以对应多个group,而一个group也同样对应多个role,我们在group.hbm.xml中加入下面的一段
<Set name=”roles” table=”t_group_role” inverse=”false” cascade=”save-update”>
<key column=”group_id”></key>
<many-to-many class=”Role” column=”role_id”/>
</Set>
其中t_group_role是group到role的映射表
我们这里将cascade设置为save-update,而不是all,因为对于delete操作,如果设置为all,这样会在删除group时候把group对应的role一样删除,这是我们不原意看到的,而设置为save-update不会有问题,在delete操作时候,不但不会删除role,同时由于设置了save-update而会更新t_group_role,删除掉t_group_role 中和group相关记录
相关的JAVA实现
Role role1=new Role();
Role role2=new Role();
Group group=new Group();
group.getRoles().add(role1);
group.getRoles().add(role2);
session.save(group);
session.flush();
对于Role.hbm.xml对groups采用类似的定义,这里不在叙述
联系客服