`

六:Hibernate的关联映射

    博客分类:
  • ssh
阅读更多
六:Hibernate的关联映射

identity 标识 
cascade 级联
inverse 反转
employee 雇员
member 成员
iterate 迭代


目标
6.1一对多关联
6.1.1面向对象领域的关联关系
6.1.2关联关系的映射配置
6.1.3通过程序维护关联关系
6.2多对多关联
6.2.1配置多对多关联
6.2.2通过程序维护多对多关联
小结:


目标:
Hibernate目标:提供一个全面的“对象-关系映射”框架。在面向对象中,学习对象间存在关联的关系。数据库中,学过表与表间 通过外键的关联。怎样映射面向对象领域的关联关系和数据库关系模型中的外键关联???

6.1一对多关联
6.1.1面向对象领域的关联关系
关联具有方向性。单向一对多,单向多对一,(将双方对关联到对方的时候)双向一对多关联(双向多对一关联)。例如:多条街道对应一个区县,一个区县对应多条街道,既可以让街道关联区县,也可以让区县关联到街道;多个老师对应一个学生,一个学生对应多个老师,既可以让老师关联到学生,也可以让学生关联到老师。
关键:不论是双向一对多,多对一,还是双向的多对一(双向一对多),都只是在观察关系时所处的位置,考虑的方面是单还是双引起的。

6.1.2关联关系的映射配置
关联关系:对象关系中的关联关系,数据库表间的,Hibernate的实体类间的。
1,单向多对一关联的映射: 实体类的定义:在多的一方(Jd类)添加一的一方(Qx类)作为属性,体现关联关系。两个类的映射文件的配置:原基本配置不变,只需要在多的一方将所添加的“一”的一方的类型的属性在<mangy-to-one/>中配置“一”的一方的信息即可(不是property节点)。例如:<many-to-one name="qx" class="Qx" column="qxid"/>,name对应在“many”方要管理的“一”的一方的属性名,column定义映射到表(实体类对应的表——TBL_JD)的字段名,将在自己这一方(多的一方)使用这个字段作为外键和“一”的一方关联;class属性为关联到“一”的一方的类别。即:单向many-to-one关系中,one的一方不变,many的一方:在实体类方面,添加one的一方类型的变量作为many一方的属性,在映射文件中,添加<many-to-one>指明one方在many方的属性名(name),类型(class),数据库表要添加作为外键来关联"one"方的表主键列(column)。
2,单向一对多关联的映射: 实体类的定义:在一的一方(Qx类)添加Set型变量(可以以多的一方的类型作为泛型约束Set<Jd>)作为属性,但需要new出来,体现关联关系。两个类的映射文件的配置:原基本配置不变,只需要在一的一方将所添加的Set类型(或Set<Jd>)的属性在<set/>中配置“一”的一方的信息即可(不是property节点)。例如:<set name="jds" ><key column="qxid" /><one-to-many class="Jd"></set>,name对应在“one”方要管理的“many”方的属性名(set型类变量的变量名),<key/>中column属性指定“many”方的外键字段名(通过在自身映射文件中配置给对方添加字段,这里是“TBL_Jd”表的字段名),将在对方(多的一方)使用这个字段作为外键和自己关联;<one-to-many>子节点中class属性为关联到“多”的一方的类别。即:单向one-to-many关系中,many的一方不变,one的一方:在实体类方面,添加set类型的变量(可以添加one方类型的泛型)作为one方的属性;在映射文件中,添加<set>节点,以指明one方以属性名(name)指明添加的类变量的变量名,<one-to-many>子节点中以(class)指明要管理的one方的类型,<key>子节点中column属性指明要给对方表"many"方在数据库要添加作为外键来关联"one"方的表主键列(column)。
3,双向多对一关联的映射: 同时配置了单向一对多和单向多对一时就成了双向一对多关联(双向多对一)。
配置关联式,考虑:程序执行效率和实际业务的需要。例如:加载街道的同时获得对应区县信息可以方便编码,但没必要通过区县对象得到下属的所有街道的数据,造成性能上的损失。
6.1.3通过程序维护关联关系
1,在many一方添加数据: 将one的一方的对象设置到many方的属性中,保存many方的对象即可。
2,在many一方删除数据: 加载many方的数据,然后调用session的delete方法,执行程序后,记录未被删除。关联是双向的,在one的一方删除,加载one方对象,在从one对象的属性中删除,然后更新,结果:执行了update语句,删除了关联关系却没有删除数据库记录(“五四大道”的qxid属性被设成了null),而且由于违反了外键约束,操作未成功。问题出在关联关系的配置上。
配置一对多关联时,set节点的inverse属性用于标识由哪一方管理双方的关联关系;inverse为false,表示有自己管理双方的关联关系,inverse为true时,表示由对方管理双方的关联关系(交出管理权给对方)。inverse(反转)为true,管理权交出去,默认为false,自己来管理。
3,修改关联关系:(前边,one方的inverse="true",关联关系由many来管理)更新many方即可更新对应的关联关系。
4,在one的一方删除数据: 直接删除one方数据,违反外键约束,抛出异常。解决:可以先删除many方数据(对应的街道数据),再删除one方数据(对应的区县数据), 执行多条delete语句,正常删除。即,想删one,先得删many才能删去one.
优化:级联更新:在关联配置中设置cascade属性,可选值(在执行相应操作是进行级联):all,none,save-update,delete。注意:如果save-update写作update-save会出现异常或者执行不成功。
6.2多对多关联
6.2.1配置多对多关联
与一对多的配置类似,只是:set节点添加table属性,值为关联表的表名,子节点<key/>的column属性为关联表中关联到自己的字段名,子节点<many-to-many/>中class设置关联属性的类型,column属性用来设定用哪个字段作为外键去关联。
6.2.2通过程序维护多对多关联
以面向对象的方式操作数据库,管理对象间的关系,首先要做好关联的配置,编写代码时只用心里有对象。

小结:
对象间的关联情况分为一对多,多对一和多对多几种情况,关联是有方向的。
Hibernate通过配置的方式,将对象的关联关系映射到数据库上。使用Hibernate关联关系,首先要做好配置。
<set>节点的inverse属性描述了有谁负责关联关系的维护;cascade属性描述了级联操作的规则。

注意(考虑):
1,持久化对象不能操作游离态对象(object references an unsaved transient instance......)!
2,控制权inverse只与save有关,即控制关系只在save,delete时建立。cascade则在所有操作下均存在!
3,A:单向many-to-one;B:单向one-to-many:one方拥有控制权(inverse=false)有弊端——性能低下,并有可能出现exception(若外键为not null时会出现null exception);级联(cascade):删除one时对应的many被提前全部删除。
C:双向one-to-many,把控制权交与many(让one方的inverse属性(反转)为true),cascade根据需要设置属性值。解释:让one方控制维护关系性能低下并有可能出现null exception,故让one的inverse为true(交出操作权)。
操作:first create one object ,then,create every many,让每一个many去save一下one就可省略update语句(提高了性能)。(意思就是,在保存每一个many时将one设置为many的属性而直接保存many即可使hibernate自动保存one并创建关系)。

例子:
双向多对多关系中的关系管理的例子(相关配置文件见文件——和):
项目与员工的关系:
项目做完了员工依然在,员工离职了项目依然在做。将级联(cascade)设置为save-update,而不是all,可以使不论使项目结束还是员工离职只影响自身和关系表而不牵扯关联表(删除时)。
然而,对关系的管理inverse,交予项目管理(让员工交出管理权,设置其inverse属性值为true)
//让项目管理关系,故,将员工集合加入项目中,再把项目保存(相应的员工也被保存)
// HashSet<Employee> proSet1=new HashSet<Employee>();
// proSet1.add(e1);
// proSet1.add(e2);
// pro1.setEmp(proSet1);
// session.save(pro1);
inverse =true 交出权限的相关配置
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics