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

以上的几个方式都可以实现hibernate的持久化对象的加载。如果有不懂hibernate对象的"临时状态"、"游离态"、"持久态"、"删除状态"的小伙伴,自己先去了解下。

对于hibernate的以上的几种检索策略,我们先来了解下他们几种的工作细节。

首先是session的load()方法,我们以Customer和Orders的例子来简单说明下。Customers与Orders的关系是一对多的关系。我们这边假定已经配置了这两个对象hbm.xml的一对多单向关联关系。

一、session的load(Customers.class,new Long(1))的方式返回的是一个Customer持久化对象的引用。这时候Customer还没有初始化。因此时不会出现sql查询语句的执行。要等到真正使用到Customer的时候才会进行初始化。也就是执行查询语句。这时候如果在Custmoers 中配置了

1 <set 
2 name="orders"
3 insever="ture"
4 lazy="true"  5 fetch= "select"6 <one-to-many class=....>
7 >

lazyd的默认属性是true,也就是说采用懒加载。

1、如果lazy设置为false的话,则会在初始化Customers对象的时候就会去将Customers所有Orders对象进行查询,这也叫立即检索。这里有个地方得值得注意的是,如果上面的set标签中配置了fecth属性为join,这时候load在真正执行查询的时候,关联对象的时候使用的的是迫切左外连接查询,这样的话,就算是显式的设置lazy的属性,也无意义。至于为什么,我想熟悉sql查询的都知道原因了。当然fecth属性还有其他的一些选项例如select,subselect,fetch默认为select。

2、如果采用懒加载,也就是lazy设置为true的话,则在初始化Customers只会对customers对象进行查询操作。而在真正使用Orders属性时才对Customers关联的Orders对象进行查询操作。这里得说明下:例如 在对Order order = customer.iterator().next()迭代的时返回是Orders的代理实例。这时的Order还没有进行实例化,所以没有进行sql查询。只有在对其属性或方法调用的时候,例如获取订单号:Order.getOrderNo()的时候才对其进行实例化。

lazy还有其他选项 extra增强 ,例如获取一个订单集合的size/contains等方法时,这时不会去初始化该orders,而是会向数据库发送一条sql去查询获取值,只有真正要用到集合元素值时才去实例化查询数据库。这种比较聪明的方式与lazy设置为true的区别就是在选择懒加载的时机上extra更加“懒惰”,更加延迟。

二、session.get(Customers.class,new Long(1))。get采用的是立即检索的策略,这里Customers一定会立马初始化。

1、 如果在对Orders的配置中,set中设置了lazy为true的话,则与load类似。等到真正使用Orders的属性的时候才会去做sql关联查询。

2、 如果 lazy设置为false,则在get()方法执行的时候也会立马初始化Orders的所有关联对象。这种方式与上面load的第一种方式唯一的区别在与,load初始化比get的初始化Customers的时机更晚,更延迟。

这里注意的是,如果如果上面的set标签中配置了fecth属性为join,关联对象的时候使用的的是迫切左外连接查询。不管lazy是否设置为true,采用的也是立即加载。

三、query接口中的list()方法。 seesion.createQuery(sql).list(),执行该方法后,程序会里面向数据库发送sql去执行查询操作。

1、 如果在对Orders的配置中,set中设置了lazy为true的话,等到真正使用Orders的属性的时候才会去做sql关联查询。

2、 如果 lazy设置为false的话,则会立马初始化Orders的所有关联对象。这个类似于get()方式。

这里有个地方需要注意下,在query.list()的时候,它会fetch的join策略的,所以就算是显式的设置了fetch为join,也不会采用迫切左外联接查询。

总结下load,get,query.list三种方式的区别:

1.load在对类级别的对象加载是有“延迟”作用的,而get和query.list采用的是立即检索的策略。

2.在关联一对多关联关系的加载时,load与get和query.list 采用的都是同样的策略,前提是在many一方的懒加载方式也是一致。

3.在get和load方式加载时,对fetch的策略是一致的。 而query.list是对fetch的join的策略是忽略的。

对于一对多的单向关联关系的懒加载策略做了大致的分析。其实双向也很好理解。

假设在Orders.hbm.xml文件中的<many-to-one> 中配置了以下配置:

1 <many-to-one

   insever="true"
   lazy = "proxy"
   ....
   class="..."

6 />

这里前提是在Customers.hbm.xml文件中的set的inserver设置为false或者不显式设置。默认为false。

1、这时在对orders对象进行加载的时候,如果customer采用的lazy是proxy方式,则采用代理懒加载方式。也就说,只有当orders获取它的custormer属性的时候,才去加载与之关联的customer对象。如果order的lazy采用的也是懒加载方式的话,则在获取customer时不会获取orders对象。

举个例子:在get(orders.class,new Long(1))的方法获取Orders的时候,会立马加载Orders对象,当获取Orders.getCustomer().getName()的时候,才会去加载Customer对象,而如果再去获取该Customer对象下的Orders的时候,才去加载Orders。也就是说会去执行3次的sql,而每次执行一条sql语句。

而如果Orders采用lazy为false的话,则与上面不用。则会在立马加载Orders,而后会在加载Customers的同时一起加载Orders对象。也就说这里也会执行3条sql, 但是分为2次执行,第一次一条查询orders,第二次两条,执行查询Customer和Orders的查询。

2、如果customer采用的lazy是no-proxy方式,则证明采用非代理懒加载,这个与上面的区别在于这种方式是,在对Orders加载完后,只有一旦获取customer属性时返回的就是Customers的实例,而不是代理实例。这样就会立马对Customers进行实例化。其他的与proxy的一致。也就是说区别在于对Customers对象的延迟加载时机的策略不同。

3、lazy的选项还可以是false,也就说。在对Orders进行加载的时候,会立马对Customers进行立刻检索。也就说会里面发出3条sql语句。2次查询order,一次查询customer。

关于hibernate的懒加载,这里讲的只涉及到了一对多的关联关系代码不多,但懂的人应该可以理解。还有一对多,一对一,多对多。。hibernate都有自己的策略,而且都很灵活。后续会给大家补上。

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

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

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

  2. Hibernate的检索策略和优化

    一.检索策略概述 当我们实现了一对多或者多对多的映射后,在检索数据库时需要注意两个问题: 1.使用尽可能小的内存:当 Hibernate 从数据库中加载一个客户信息时, 如果同时加载所有关联这个客户的 ...

  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检索策略

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

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

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

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

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

  8. hibernate(八) Hibernate检索策略(类级别,关联级别,批量检索)详解

    序言 很多看起来很难的东西其实并不难,关键是看自己是否花费了时间和精力去看,如果一个东西你能看得懂,同样的,别人也能看得懂,体现不出和别人的差距,所以当你觉得自己看了很多书或者学了很多东西的时候,你要 ...

  9. Hibernate 检索策略

    概述 检索数据时的 2 个问题: –不浪费内存:当 Hibernate 从数据库中加载 Customer 对象时, 如果同时加载所有关联的 Order 对象, 而程序实际上仅仅需要访问 Custome ...

随机推荐

  1. glusterfs 术语

    Access Control Lists Access Control Lists (ACLs) allows you to assign different permissions for diff ...

  2. IntelliJ IDEA的下载、安装和WordCount的初步使用(本地模式和集群模式)

    包括: IntelliJ IDEA的下载  IntelliJ IDEA的安装 IntelliJ IDEA中的scala插件安装 用SBT方式来创建工程 或 选择Scala方式来创建工程 本地模式或集群 ...

  3. hdoj 1253 胜利大逃亡

    胜利大逃亡 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  4. 关于.net的一些基础知识(一)

    一.GC工作原理: GC如其名,就是垃圾收集,当然这里仅就内存而言.Garbage Collector(垃圾收集器,在不至于混淆的情况下也成为GC)以应用程序的root为基础,遍历应用程序在Heap上 ...

  5. 使用 Infragistics 的 NetAdvantage 组件时替换部分菜单语言的方法

    Infragistics 的 NetAdvantage 组件很好用,不过有些自动的菜单默认都是英文的,一直想替换成中文,以下就是研究了一下午整出来的几行代码,貌似网上很难找到此类的相关资料,替换的资源 ...

  6. 前缀、中缀、后缀表达式及其相互转化的Java实现

    一.中缀表达式转换为前缀.后缀表达式 给个中缀表达式:a+b*c-(d+e)    首先根据运算符的优先级给所有运算单位加括号:((a+(b*c))-(d+e))    将运算符号移动到对应括号的前面 ...

  7. Dom4j写XML

    package com; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.I ...

  8. DTrace patch for Python 2.7.x and 3.x

    DTrace patch for Python 2.7.x and 3.x Última Actualización: 21 de septiembre de 2015 https://www.jce ...

  9. QtSpeech会让Qt说话

    想要多了解QtSpeech,那么随着本文的文字往下走吧!QtSpeech是一个Qt封装的跨平台TTS(文本变成语音输出)API,在不同平台下利用系统自带的TTS引擎.在Windows下使用SAPI, ...

  10. 关于Intent的七大属性

    原谅我愚昧,Intent七大属性这个概念我也是昨天才接触到,看了一下,都是一些常用的东西,就是没有总结过,那么今天就来简单总结一下. Intent七大属性是指Intent的ComponentName. ...