本文依旧以Customer类和Order类进行说明。
一、引言
  Hibernate检索Customer对象时立即检索与之关联的Order对象,这种检索策略为立即检索策略。立即检索策略存在两大不足:
    A、select语句太多,而且会出现N+1的问题。所谓N+1,1是指先查出所有的Customer集合,N是指针对每个Customer再查询其关联的Order集合。N+1可以通过一条外连接查询语句完成。
    B、应用逻辑上可能并不需要Order集合,此时加载Order集合浪费内存空间。
  为解决上述问题,Hibernate提供了另外两种检索策略:延迟检索策略和迫切左外连接检索策略。
二、Hibernate的检索策略简介
  分两个层次:类级别检索策略和关联级别的检索策略。
  1、类级别和关联级别可选的检索策略及默认的检索策略

检索策略的作用域 可选的检索策略 默认的检索策略 运行时行为受影响的检索方法
类级别 立即检索
延迟检索
延迟检索 仅Session.load()方法。其余的都是立即检索
关联级别 立即检索
延迟检索
迫切左外连接检索
延迟检索 影响Session.load()及get()方法,Query API以及Criteria API。Query API会忽略映射文件中设定的迫切左外连接检索策略

  2、三种检索策略的允许机制

检索策略的类型 类级别 关联级别
立即检索 立即加载检索方法指定的对象 立即加载与检索方法指定的对象关联的对象。可以设定批量检索数量。
延迟检索 延迟加载检索方法指定的对象 延迟加载与检索方法指定的对象关联的对象。可以设定批量检索数量。
迫切左外连接检索 不适用 通过左外连接加载与检索方法指定的对象关联的对象。

  3、用于设定检索策略的几个属性

属性 类级别 一对多关联级别 多对一关联级别
lazy <class>元素中可选值为:true(延迟)和false(立即) <set>元素中可选值:true(延迟)、extra(增强延迟)和false(立即) <many-to-one>元素中的可选值:proxy(延迟)、no-proxy(无代理延迟)和false(立即)
fetch <set>元素中可选值:select(select查询语句)、subselect(带子查询的查询语句)和join(迫切左外连接查询) <many-to-one>元素中可选值:select(select查询语句)、和join(迫切左外连接查询)
batch-size 设定批量检索的数量。仅适用于关联级别的立即检索和延迟检索。
备注 fetch属性取值为select或subselect时,决定初始化关联集合的查询语句的形式;取值为join时,决定集合被初始化的时机。若fetch属性为join,则lazy属性被忽略。

三、类级别的检索策略
  类级别可选的检索策略包含立即检索和延迟检索,默认是立即检索。
  通过以下配置文件:

<class name="mypack.Customer" table="CUSTOMERS" lazy="true/false">

  且只在Session.load()方法时生效,其返回的是一个代理对象,注意与其相关的几种异常。可以通过org.hibernate.Hibernate#initialize()方法显式初始化代理类实例。
四、一对多和多对多关联的检索策略
1、立即检索(lazy属性为false):慎用。
2、延迟检索(lazy属性为true):只有当应用程序第一次访问集合对象时才初始化,比如调用集合的iterator()\size()\isEmpty\contains()方法时。
3、增强延迟检索(lazy属性为extra):与延迟检索类似,但是只有调用集合的iterator()方法时,才会初始化集合对象。
4、批量延迟检索和批量立即检索(使用batch-size属性)
  该属性的设置可以对N+1的问题起到缓解效果。
  举例说明:一个Customer对象的orders集合中有10个对象,正常情况下全部加载会执行11条语句。
  设置了batch-size为4后,将会执行1+3条语句。

select * from CUSTOMERS;
select * from ORDERS where CUSTOMER_ID in (1,2,3,4);
select * from ORDERS where CUSTOMER_ID in (5,6,7,8);
select * from ORDERS where CUSTOMER_ID in (9,10);

5、用带子查询的select语句整批量初始化orders集合(fetch属性为subselect)
即在初始化集合时会采用子查询的方式。
当fetch属性为subselect时,batch-size属性失效。
6、迫切左外连接查询(fetch属性为join):直接使用左外连接查询初始化集合对象。
注意,当使用Query.list()时,该配置失效。
五、多对一和一对一关联的检索策略
1、迫切左外连接(fetch属性为join):与上述类似,注意和lazy属性的搭配。
2、延迟检索(lazy属性为proxy):对于一对一关联,如果使用延迟加载,必须把<one-to-one>元素的constrained属性设置为true。
3、无代理延迟加载(lazy属性为no-proxy):无代理的延迟检索会在order.getCustomer()时就进行初始化,而又代理的延迟加载时在访问Customer属性时初始化。
4、立即检索(lazy属性为false):与上述类似。
5、批量延迟检索和批量立即检索(使用batch-size属性):与上述类似。
六、控制迫切左外连接检索的深度
  通过hibernate.max_fetch_depth属性来控制,默认值为2.
七、属性级别的检索策略
  主要是针对<property><component>元素,适合于二进制大对象、字符串大对象及大容量组件类型的属性。

攻城狮在路上(壹) Hibernate(十二)--- Hibernate的检索策略的更多相关文章

  1. 攻城狮在路上(壹) Hibernate(十八)--- 管理Hibernate的缓存

    一般Session的缓存被称为Hibernate的第一级缓存,SessionFactory的外置缓存是一个可配置的缓存插件,称为Hibernate的第二级缓存.一.缓存的基本原理: 1.持久化层的缓存 ...

  2. 攻城狮在路上(壹) Hibernate(十六)--- Hibernate声明数据库事务

    一.数据库事务的概念: 数据库的ACID特征:Atomic.Consistency.Isolation.Durability.原子性.一致性.隔离性.持久性.不同的隔离级别引发的不同问题. 事务的AC ...

  3. 攻城狮在路上(壹) Hibernate(十四)--- Hibernate的检索方式(下)

    本节介绍HQL和QBC的高级用法:各种连接查询.投影查询.报表查询.动态查询.集合过滤和子查询等.另外将归纳优化查询程序代码,从而提高查询性能的各种技巧.一.连接查询: HQL与QBC支持的各种连接类 ...

  4. 攻城狮在路上(壹) Hibernate(十三)--- Hibernate的检索方式(上)

    Hibernate提供了以下几种检索对象的方式: A.导航对象图检索方式. B.OID检索方式.Session.get() load(); C.HQL检索方式.Query. D.QBC检索方式.Que ...

  5. 攻城狮在路上(壹) Hibernate(九)--- Hibernate的映射类型

    Hibernate采用映射类型作为Java类型和SQL类型的桥梁,对应type属性.分为两种:内置映射类型和客户化映射类型.一.内置映射类型: 1.Java基本类型的Hibernate映射类型: Ja ...

  6. 攻城狮在路上(壹) Hibernate(七)--- 通过Hibernate操纵对象(下)

    一.与触发器协同工作: 当Hibernate与数据库的触发器协同工作时,会出现以下两类问题: 1.触发器使Session缓存中的数据和数据库中的不一致: 出现此问题的原因是触发器运行在数据库内,它执行 ...

  7. 攻城狮在路上(壹) Hibernate(六)--- 通过Hibernate操纵对象(上)

    一.Hibernate缓存简介: Session接口是Hibernate向应用程序提供的操纵数据接口的最主要接口,它提供了基本的保存.更新.删除和加载Java对象的方法. Session具有一个缓存, ...

  8. 攻城狮在路上(壹) Hibernate(三)--- 属性访问、命名策略、派生属性、指定包名等

    一.hibernate访问持久化类属性的策略: 在<property>元素中的access属性用于指定Hibernate访问持久化类属性的方式. 常见的方式如下: 1.property:默 ...

  9. 攻城狮在路上(壹) Hibernate(二)--- 第一个hibernate程序

    1.直接通过JDBC API持久化实体域对象: A.java.sql常用接口和类: DriverManager:驱动程序管理器,负责创建数据库连接. Connection:代表数据库连接. State ...

随机推荐

  1. Tomcat异常 Multiple Contexts have a path of "/qqshl".解决方法

    Tomcat异常 Multiple Contexts have a path of "/qqshl".解决方法 找到tomcat映射文件Service.xml,将文件中的conte ...

  2. Graph Valid Tree

    Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), ...

  3. 如何用 Robotframework 来编写优秀的测试用例

    介绍 这篇文档将会是一篇在「高层面」的怎么用 Robotframework 来编写优秀测试用例的原则.至于如何使用 Robotframework 来与您的待测试系统相作用这样的细节讨论是不包含在这篇文 ...

  4. 请不要用SECONDS_BEHIND_MASTER来衡量MYSQL主备的延迟时间【转】

    本文来自:http://www.woqutech.com/?p=1116 MySQL 本身通过 show slave status 提供了 Seconds_Behind_Master ,用于衡量主备之 ...

  5. Make My GitHub Pages

    https://git-scm.com/ https://pages.github.com/ 1.建立repository. 2.settings 3.选模板 4.Publish http://use ...

  6. ABAP 内表的行列转换-发货通知单-打印到Excel里

    需要传入数据到Excel里的模板如上图所示 ********************** *           设计主要逻辑与原理说明                                 ...

  7. OKhttp的封装(下)

    OKhttpManager2.Class  请求工具类 package com.example.administrator.okhttp3; import android.os.Handler; im ...

  8. 51nod 1070 Bash游戏 V4 (斐波那契博弈)

    题目:传送门. 有一堆个数为n(n>=2)的石子,游戏双方轮流取石子,规则如下: 1)先手不能在第一次把所有的石子取完,至少取1颗: 2)之后每次可以取的石子数至少为1,至多为对手刚取的石子数的 ...

  9. 假期(codevs 3622)

    题目描述 Description 经过几个月辛勤的工作,FJ决定让奶牛放假.假期可以在1-N天内任意选择一段(需要连续),每一天都有一个享受指数W.但是奶牛的要求非常苛刻,假期不能短于P天,否则奶牛不 ...

  10. 把Git Repository建到U盘上去(转)

    把Git Repository建到U盘上去 转 把Git Repository建到U盘上去 Git很火.原因有三: 它是大神Linus Torvalds的作品,天然地具备神二代的气质和品质: 促进了生 ...