从昨晚后半夜开始下午,现在外面的雪还没停,这是来北京后最大的一场雪。早上6:30起床,然后去吃早餐。今天是元旦假期的最后一天,幸好乘车的人不多,很快就坐上了车。如果是平时可能得在大雪里走几站,甚至走到学校。气温还可以,在外面等车时,雪好美!
今日继续讲解hibernate,也是hibernate课程的最后一天。Hibernate的内容非常多,如果详细着讲估计还得两天,但课程安排是三天。大部分之前的学生说外面用hibernate的很少!~~ 无奈!继续上一次课程…。
一、Hibernate的检索策略
上一次课程我们学习了类级别的检索策略和关联级别的一对多检索策略,简单复习一下:
一对多关联检索:
Fecth lazy
|
True
|
false
|
extra
|
Join
|
迫左
|
迫左
|
迫左
|
Select
|
延迟
|
立即
|
延迟(特别)
|
subselect
|
|
|
|
Fecth的优先级别高于lazy
延迟(特别):select count(id) from orders where cid=?
Subselect:使用嵌套子查询,批量查询的时候。
多对一关联检索:
Fecth lazy
|
false
|
proxy
|
No-proxy
|
Join
|
迫左
|
迫左
|
迫左
|
Select
|
立即
|
延迟:对端类级别是延迟
立即:对端类级别是立即
|
|
表单所属的客户,客户是表单的一级关联,再取出客户对应的所有表单,此时表单是前一个表单的二级关联。一级关联、二级关联,两次左外连接使用一条语句的话,会降低性能。所以使用了一条左边连接查询和一条查询语句。这就是著名的N+1查询。
hibernate3.0的所有检索策略都为延迟
接下来我们继续学习关联级别的一对一检索策略与多对多检索策略。
1.一对一检索策略
一对一关联关系是一种什么样的关系?一对一关系不可以把他们定义为一个类吗?把他们放在一个表里不可以吗?当然可以!
一对一关联两种方案:
1).外键关联,此种解决方案有两种方法:
老徐举的例子,一个用户表对应一个地址。为什么要这么做?假设地址中包含大字段,这样可以减少资源的浪费,提高访问性能。
l 方法一、就是在多对一关联的元素节点中添加一个unique=”true”属性便形成了一对一关联。
在用户类的映射文件中添加:
<!-- 影射一对一外键关联用many-to-one进行模拟,增加唯一性约束 -->
<many-to-one name="addr" column="aid" class="AddrFk" unique="true" />
|
在地址类的映射文件中添加:
<one-to-one name="user" property-ref="addr"/>
|
l 方法二、直接使用一对一关系:
在用户类的映射文件中添加:
<!-- 影射一对一主键关联 -->
<one-to-one name="addr" class="AddrPk" />
|
在地址类的映射文件中添加:
<one-to-one name="user" class="UserPk" constrained="true"/>
|
同时我们需要设置地址类映射文件的主键为:
<id name="id" column="id" type="integer">
<generator class="foreign">
<param name="property">user</param>
</generator>
</id>
|
将用户表的主键设置为地址表的外键。
2).主键关联,此时子表的主键与主表的主键一一对应。有三种解决方案:
老徐举了一个例子:员工有钟点工和普通工人之分,钟点工领取的是时效工资(rate),普通工人领取的是月薪(salary)。所以我们有必要提取一个员工的超类,并分别实现钟点工和普通工人的子类。
l 方法一、我们将钟点工和普通工人的信息放到一个表里,需要在映射文件中添加:
<!-- 区分符 -->
<discriminator column="etype" type="string" length="2" />
<property name="name" column="name" type="string" length="15" />
<!-- 子类(整个继承关系树对应于一个表) -->
<subclass name="HeSingle" discriminator-value="he" lazy="false">
<property name="rate" column="rate" type="float" />
</subclass>
<subclass name="SeSingle" discriminator-value="se" lazy="false">
<property name="salary" column="salary" type="float" />
</subclass>
|
注意“discriminator”元素用于定义一个额外的列,用于区分员工的类型。
l 方法二、我们为每类员工都分别建一个表,如:
<!-- 每个子类对应一个表,从表和主表间一对一关系 -->
<joined-subclass name="HeJoined" table="hib_hejoineds" lazy="false">
<key column="eid" />
<property name="rate" column="rate" type="float" />
</joined-subclass>
<joined-subclass name="SeJoined" table="hib_sejoineds" lazy="false">
<key column="eid" />
<property name="salary" column="salary" type="float" />
</joined-subclass>
|
“column="eid"”被做为外键对应主表的员工id。
l 方法三、为每类员工建立一个表,他们与主表无关各自具有全字段。但是这三个表所使用的Id是不重复的:
<union-subclass name="HeUnion" table="hib_heunions">
<property name="rate" column="rate" type="float" />
</union-subclass>
<union-subclass name="SeUnion" table="hib_seunions">
<property name="salary" column="salary" type="float" />
</union-subclass>
|
此时,我们需要使用一个特殊的主键增值生成器:
<id name="id" column="id" type="integer">
<generator class="hilo">
<param name="table">hib_hilo</param>
<param name="column">currvalue</param>
<param name="max_lo">10</param>
</generator>
</id>
|
“"max_lo"”是id取值区间,每次插入记录时,生成器会根据此值步长增长。如果我们执行的一次插入操作,插入了10条记录。那么就需要将此设置为10,以便生成器自动为我们生成10个不同的id。
2.多对多检索策略
在以前的学习中,我们知道多对多关联关系需要一个中间表,用于记录两个多对多表的对应主键。反应到映射文件中,我们需要为两个类添加set元素。我们依然使用,老师与学生的例子,一个老师可以有多个学生,一个学生可以有多个老师,映射文件如下:
老师类映射文件中的set元素:
<set name="stus" table="hib_tea_stu_links" lazy="false">
<key column="tid" />
<many-to-many class="Stu" column="sid" />
</set>
|
“column="tid"”对应中间表“hib_tea_stu_links”的老师外键。“column="sid"”对应中间表“hib_tea_stu_links”学生的外键。
学生类映射文件中的set元素:
<set name="teas" table="hib_tea_stu_links" lazy="false" inverse="true">
<key column="sid" />
<many-to-many class="Tea" column="tid" />
</set>
|
检索策略
|
优点
|
缺点
|
优先考虑使用的场合
|
立即检索
|
对应用程序完全透明,不管对象处于持久化状态还是游离状态,应用程序都可以从一个对象导航到关联的对象
|
(1)select语句多
(2)可能会加载应用程序不需要访问的对象,浪费许多内存空间。
|
(1)类级别
(2)应用程序需要立即访问的对象
(3)使用了二级缓存
|
延迟检索
|
由应用程序决定需要加载哪些对象,可以避免执行多余的select语句,以及避免加载应用程序不需要访问的对象。因此能提高检索性能,并节省内存空间。
|
应用程序如果希望访问游离状态的代理类实例,必须保证她在持久化状态时已经被初始化。
|
(1)一对多或者多对多关联
(2)应用程序不需要立即访问或者根本不会访问的对象EN-U
分享到:
Global site tag (gtag.js) - Google Analytics
|
相关推荐
传智播客hibernate源码 传智播客hibernate源码
传智播客 hibernate PPT 很经典
41_传智播客hibernate教程_hibernate二级缓存的扩充细节.rar
传智播客Hibernate课件.ppt
传智播客_hibernate 传智播客 hibernate ppt
传智播客\传智播客hibernate\01_传智播客hibernate教程_hibernate介绍与动手入门体验
传智播客hibernate教程.ppt传智播客hibernate教程.ppt传智播客hibernate教程.ppt传智播客hibernate教程.ppt传智播客hibernate教程.ppt
传智播客hibernate教程_PPT.ppt
传智播客-hibernate框架开发视频第day01-day04资料 传智播客-hibernate框架开发视频第day01-day04资料
传智播客的Java Web课程的ppt关于数据库持久的框架Hibernate
传智播客 Hibernate源码
传智播客视频里李勇hibernate视频用的PPT
03_传智播客hibernate教程_hibernate入门案例的代码优化
传智播客李勇hibernate 李勇老师讲解的内容细致广泛,深入浅出,很适合入门和刚学习hibernate的童鞋
传智播客李勇hibernate源码1-20课,目录如下:01_hibernate介绍与动手入门体验;02_hibernate入门案例的细节分析; 03_hibernate入门案例的代码优化; 04_Session接口及get|load|persist方法 05_实体对象的三种状态...
传智播客Hibernate课件
传智播客 hibernate 完全学习文档,没有更好