本文依旧以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. int *const && int const * && const int *的区别

    ANSIC允许声明常量,常量和变量不同,常量就是不可以改变的量,用关键字const来修饰 比如:const int a int const a 以上两种声明方式是一样的,我们不需要考虑const和in ...

  2. Webclent基本操作

    /** * @Title: webclientTest.java * @Package webclient * @Description: TODO(用一句话描述该文件做什么) * @author A ...

  3. java对txt文件内容追加

    package com.test; import java.io.FileOutputStream; /** * 对txt文件在文本追加内容 * @author Wdnncey * */ public ...

  4. 【leetcode】Reverse Linked List II

    Reverse Linked List II Reverse a linked list from position m to n. Do it in-place and in one-pass. F ...

  5. C#之枚举类型

    参考: http://www.cnblogs.com/an-wl/archive/2011/04/14/2015815.html 惯例先上MSDN: https://msdn.microsoft.co ...

  6. 解读Unity中的CG编写Shader系列十 (光滑的镜面反射(冯氏着色))

    前文完成了最基本的镜面反射着色器,单平行光源下的逐顶点着色(per-vertex lighting),又称为古罗着色(Gouraud shading).这篇文章作为后续讨论更光滑的镜面反射方式,逐像素 ...

  7. TransactionScope类

    命名空间:System.Transactons MSDN解释:使代码块成为事务性代码,此类不能被继承. 百度空间:在项目中引用using System.Transaction命名空间.在using 中 ...

  8. android 和iOS的view上的区别

    android上的view的类叫View, 以下是它的class overview, This class represents the basic building block for user i ...

  9. filter 简介

    概述 filter() 方法使用指定的函数测试所有元素,并创建一个包含所有通过测试的元素的新数组. 语法 var new_arrary = arr.filter(callback[, thisArg] ...

  10. struts.xml配置

    1. package标签 package:完成有业务相关的Action(应用控制器的)管理 name:给包起的名字(反映该包中Action的功能),用来完成包和包之间的继承.默认继承struts-de ...