一、检索策略概述

当我们实现了一对多或者多对多的映射后,在检索数据库时需要注意两个问题:

1、使用尽可能小的内存:当 Hibernate 从数据库中加载一个客户信息时, 如果同时加载所有关联这个客户的订单信息, 而程序实际上仅仅需要访问客户信息, 那么这些关联的 订单信息就白白浪费了许多内存。

2、更高的查询效率:发送尽可能少的 SQL 语句。

二、类级别的检索策略(class标签中设置)

类级别可选的检索策略包括立即检索和延迟检索, Hibernate默认采用延迟检索。

类级别的检索策略可以通过 <class> 元素的 lazy 属性进行设置。

若 <class> 元素的 lazy 属性为 true 或取默认值, Session 的 load() 方法不会执行查询数据表的 SELECT 语句, 仅返回代理类对象的实例, 该代理类实例有如下特征:

1、由 Hibernate 在运行时采用 CGLIB 工具动态生成。

2、Hibernate 创建代理类实例时, 仅初始化其 OID 属性

3、在应用程序第一次访问代理类实例的非 OID 属性时, Hibernate 会初始化代理类实例。

如果程序加载一个对象的目的是为了访问它的属性, 可以采取立即检索。如果程序加载一个持久化对象的目的是仅仅为了获得它的引用, 可以采用延迟检索。会出现懒加载异常!(获取具体属性之前session关闭了就会出现)。

注意:无论 <class> 元素的 lazy 属性是 true 还是 false, 只是针对load()方法设置有效。Session 的 get() 方法及 Query 的 list() 方法在类级别总是使用立即检索策略。

配置形式:

<class name="Customer" table="CUSTOMERS" lazy="false">

二、一对多的检索策略(set标签中设置)

在映射文件中, 用 <set> 元素来配置一对多关联及多对多关联关系.。<set> 元素有 lazy 和 fetch 属性,还有一个batch-size 属性。

lazy: 主要决定集合被初始化的时机。

fetch: 取值为 “select” 或 “subselect” 时, 决定初始化集合的查询语句的形式;  若取值为”join”, 则决定集合被初始化的时机。若把 fetch 设置为 “join”, lazy 属性将被忽略。

<set> 元素的 batch-size 属性:用来为延迟检索策略或立即检索策略设定批量检索的数量。批量检索能减少 SELECT 语句的数目, 提高延迟检索或立即检索的运行性能。

1、lazy属性

在延迟检索(lazy 属性值为 true) 集合属性时, Hibernate 在以下情况下初始化集合代理类实例 。

1)应用程序第一次访问集合属性: iterator(), size(), isEmpty(), contains() 等方法。

2)通过 Hibernate.initialize() 静态方法显式初始化。

增强延迟检索(lazy 属性为 extra): 与 延迟检索类似,主要区别是增强延迟检索策略能进一步延迟 Customer 对象的 orders 集合代理实例的初始化时机。具体来说

1)当程序第一次访问集合属性的 iterator() 方法时, 会导致集合代理类实例的初始化。

2)当程序第一次访问集合属性的 size(), contains() 和 isEmpty() 方法时, Hibernate 不会初始化集合类的实例, 仅通过特定的 select 语句查询必要的信息。

推荐使用默认值lazy=true即延迟检索的方式。

2、fetch属性

1)默认值为 select,即通过正常的方式来初始化 set 集合元素。

2)可以取值为 subselect,通过子查询的方式来初始化所有的 set 集合。子查询作为 where 子句的 in 的条件出现, 子查询查询的是所有 1 的那一端的 ID,此时 lazy 设置有效,但 batch-size 失效。 

3)若取值为 join,则在加载 1 的那一端的对象时, 使用迫切左外连接(使用左外链接进行查询, 且把集合属性进行初始化)的方式检索 n 的一端的集合属性。并且忽略 lazy 属性。

注意:HQL 查询忽略 fetch=join 这个设置。即Query 的list() 方法会忽略映射文件中配置的迫切左外连接检索策略, 而依旧采用延迟加载策略。

3、 batch-size属性

set 元素的 batch-size 属性: 设定一次初始化 set 集合的数量,可以减少sql语句。

一对多(多对多)的检索策略的配置方法

<set name="orders" table="ORDERS"  lazy="true"  batch-size="2"  fetch="subselect">

三、多对一(一对一)检索策略(<many-to-one> 标签中设置)

<many-to-one> 元素也有一个 lazy 属性和 fetch 属性。

1、lazy属性

lazy 取值为proxy 代表对应的属性采用延迟检索,默认情况是延迟检索。

lazy 取值为false
代表对应的属性采用立即检索。

2、fetch 属性

fetch默认值为 select,即通过正常的方式来初始化 set 集合元素。

fetch 取值为 join, 表示使用迫切左外连接的方式初始化 n 关联的 1 的一端的属性,且忽略 lazy 属性的设置。

迫切左外连接检索策略的优点在于比立即检索策略使用的 SELECT 语句更少。

3、batch-size属性

注意:该属性需要设置在 1 那一端的 class 元素中:

<class name="Customer" table="CUSTOMERS" lazy="true" batch-size="5">

作用: 一次性初始化 1 的这一段代理对象的个数。

4、注意:

1)Query 的 list 方法会忽略映射文件配置的迫切左外连接检索策略, 而采用延迟检索策略。

2)如果在关联级别使用了延迟加载或立即加载检索策略, 可以设定批量检索的大小, 以帮助提高延迟检索或立即检索的运行性能。

3)Hibernate 允许在应用程序中覆盖映射文件中设定的检索策略。

多对一(一对一)检索策略的配置方法:

<class name="Customer" table="CUSTOMERS"  batch-size="5">

<many-to-one name="customer" class="Customer" column="CUSTOMER_ID" lazy="false" fetch="join"></many-to-one>

四、三种检索策略的比较

1、立即检索

采用立即检索策略,会把被检索的对象,以及和这个对象关联的一对多对象都加载到缓存中。Session的get方法就使用的立即检索策略。

这种策略的优点在于,对应用程序完全透明,不管对象处于持久化状态,还是游离状态,应用程序都可以方便的从一个对象导航到与它关联的对象。

缺点就是,一方面select语句太多;另一方面可能会加载应用程序不需要访问的对象白白浪费许多内存空间。

适用场合:

1)类级别的访问

2)需要立即获取对象信息

3)采用了二级缓存





2、延迟检索

采用延迟检索策略,就不会加载关联对象的内容。直到第一次获取关联对象的相关属性时,才去加载关联对象。在不涉及关联类操作时,延迟检索策略只适用于Session的load方法。涉及关联类操作时,延迟检索策略也能够适用于get,list等操作。

在类级别操作时, 延迟检索策略,只加载类的OID不加载类的其他属性,只用当第一次访问其他属性时,才回访问数据库去加载内容。(这里使用了CGLIB生成了类的代理类)。

在关联级别操作时,延迟检索策略,只加载类本身,不加载关联类,直到第一次调用关联对象时,才去加载关联对象。

 默认模式都是用延迟加载策略。如果需要指定使用延迟加载策略。在配置文件中设置<class>的lazy=true,<set>的lazy=true或extra(增强延迟)<many-to-one>的lazy=proxy和no-proxy。

优点在于:由程序决定加载哪些类和内容,而不必全部都加载,避免了内存的大量占用和数据库的频繁访问。因此能提高检索性能,并且能节省内存空间。

缺点:在Session关闭后,就不能访问关联类对象了。 需要确保Session一直处于打开状态,调用关联对象,最后在关闭Session对象。应用程序如果希望访问游离状态代理类实例,必须保证他在持久化状态时已经被初始化。

适用场合:

1)一对多或多对多关联

2)不需要立即 访问对象信息或不需要访问。





3、左外连接检索

采用左外连接检索,能够使用Sql的外连接查询,将需要加载的关联对象加载在缓存中。<set>fetch设置为join,<many-to-one>的fetch设置为join。

优点在于:对应用程序完全透明,不管对象处于持久化状态,还是游离状态,应用程序都可以方便的从一个对象导航到与它关联的对象。使用了外连接,select语句数目少。缺点:可能会加载应用程序不需要访问的对象,白白浪费许多内存空间。复杂的数据库表连接也会影响检索性能。

适用场合:

1)多对一或多对多关联

2)需要立即访问对象信息

3)数据库具有良好的表连接性能

Hibernate的检索策略和优化的更多相关文章

  1. 攻城狮在路上(壹) Hibernate(十二)--- Hibernate的检索策略

    本文依旧以Customer类和Order类进行说明.一.引言: Hibernate检索Customer对象时立即检索与之关联的Order对象,这种检索策略为立即检索策略.立即检索策略存在两大不足: A ...

  2. Hibernate的检索策略

    hibernate 的中的session依照load()和get()按照参数的制定OID(ObjctID)去加载一个持久化对象.另外Query.list()方法则按照HQL语句去加载持久化的对象. 以 ...

  3. Hibernate逍遥游记-第7章 Hibernate的检索策略和检索方式(<set lazy="false" fetch="join">、left join fetch、FetchMode.JOIN、)

    1. <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hi ...

  4. Hibernate —— 检索策略

    一.Hibernate 的检索策略本质上是为了优化 Hibernate 性能. 二.Hibernate 检索策略包括类级别的检索策略.和关联级别的检索策略(<set> 元素) 三.类级别的 ...

  5. Hibernate检索策略与检索方式

    hibernate的Session在加载Java对象时,一般都会把鱼这个对象相关联的其他Java对象也都加载到缓存中,以方便程序的调用.但很多情况下,我们不需要加载太多无用的对象到缓存中,一来会占用大 ...

  6. Hibernate检索策略

    1. Hibernate的检索策略概述: 检索数据时的 2 个问题:    1.不浪费内存:当 Hibernate 从数据库中加载 Customer 对象时, 如果同时加载所有关联的 Order 对象 ...

  7. Java实战之02Hibernate-05检索策略、检索方式

    十一.Hibernate的检索策略 1.概述: 查询的时机:什么时候去查? /** * 一张表的检索策略我们称之为: * 类级别的检索策略. * 注意:只要是说类级别的检索策略,就一定不涉及关联对象. ...

  8. Hibernate检索策略(抓取策略)(Hibernate检索优化)

    一.查询方法中get方法采用策略是立即检索,而load方法采用策略是延迟检索,延迟检索是在使用数据时才发送SQL语句加载数据 获取延迟加载数据方式:1.使用的时候,如果Customer c=sessi ...

  9. Hibernate学习---检索优化

    Hibernate框架对检索进行了优化,前面我们将CURD的时候提到了load和get的区别,当时仅仅说了load为延迟加载,get为立即加载,当检索的记录为空的时候load报错(不是在执行load方 ...

随机推荐

  1. hdu3572 任务分配/最大流判断满流

    题意:将n个任务分配为m个机器,给每个任务需要的天数(无需每天连续),和可以在哪些天去做该任务,求是否存在方案. 典型的任务(X)----天(Y)二分最大流,(因为这里任务是与天的关系)处理器控制流量 ...

  2. UVA 11090 Going in Cycle!! SPFA判断负环+二分

    原题链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...

  3. 转载:P2P技术原理及应用(1)

    转帖allen303allen的空间 作 者:金海 廖小飞 摘要:对等网络(P2P)有3种主要的组织结构:分布式哈希表(DHT)结构.树形结构.网状结构.P2P技术已 经延伸到几乎所有的网络应用领域, ...

  4. 快速掌握分布式搜索引擎ElasticSearch(一)

    前言 由于最近在项目中接触使用到了ElasticSearch,从本篇博客开始将给大家分享这款风靡全球的产品.将涉及到ElasticSearch的安装.基础概念.基本用法.高级查询.中文分词器.与Spr ...

  5. es6系列-变量声明

    es6系列所有文章都是阅读阮一峰老师的<ES6标准入门>(第2版)所做的读书笔记.方便日后查阅相关基础知识. git地址: https://github.com/rainnaZR/es6- ...

  6. sql server trace

    http://www.cnblogs.com/zhijianliutang/p/4113911.html http://www.cnblogs.com/studyzy/archive/2009/01/ ...

  7. 邁向IT專家成功之路的三十則鐵律 鐵律二十二:IT人升遷之道-無為

    升遷管道是許多人求職時相當重要的考量之一,畢竟人除了很愛錢之外更愛顯赫的頭銜,然而在企業中越顯赫的頭銜,其背後通常有更多的罵名,因為許多人的高官厚爵都是踩著一群人的頭頂爬上去的,隨時哪一天跌了下來,都 ...

  8. 使用TypeDescriptor给类动态添加Attribute【转】

    源文 : http://www.cnblogs.com/bicker/p/3326763.html 给类动态添加Attribute一直是我想要解决的问题,从msdn里找了很久,到Stack Overf ...

  9. 随想录(fatfs的学习)

    [ 声明:版权全部,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 上学的时候就对文件系统非常有兴趣.可是苦于没有合适的fs代码能够学习.市面上的fs代码,要么太 ...

  10. python 依照list中的dic的某key排序

    面试题之中的一个. s=[ {"name":"Axx","score":"90"}, {"name" ...