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. PAT 1075. PAT Judge (25)

    题目地址:http://pat.zju.edu.cn/contests/pat-a-practise/1075 此题主要考察细节的处理,和对于题目要求的正确理解,另外就是相同的总分相同的排名的处理一定 ...

  2. IOS GCD 使用(三)单例模式

    一  Dispatch_once函数简介      使用dispatch_once提价的代码块,即便你提交多次,只能执行一次.    void dispatch_once(dispatch_once_ ...

  3. JavaScript高级程序设计—阅读笔记(第一部分)

    第一章 JavaScript简介1.JavaScript组成(核心(ECMAScript),文档对象模型(DOM),浏览器对象模型(BOM))2.文档对象模型(DOM),提供访问和操作网页内容的方法和 ...

  4. Ubuntu 12.04 64bit 配置完android 5.0编译环境后出现“could not write bytes: Broken pipe.”而无法进入输入帐号密码的登陆界面

    Ubuntu 12.04 64bit 配置完android 5.0编译环境后出现“could not write bytes: Broken pipe.”而无法进入输入帐号密码的登陆界面.上网问了问百 ...

  5. 前端JS开发框架-DHTMLX--dhtmlXTree

    介绍 dhtmlxTree是一个功能丰富的JavaScript树菜单  它允许您快速添加一个好看的,基于ajax的web页面的分层树. treeview支持在线节点编辑.先进的拖放,三态复选框等等.由 ...

  6. java14 处理流

    二.处理流 .引用类型,保留数据+类型 序列化:将对象保存到文件或者字节数组中保存起来,叫序列化.输出流:ObjectOutputStream.writeObject(). 反序列化:从文件或者字节数 ...

  7. bash shell for循环1到100 .

    前言 用bash shell写程序时,经常会用到for循环,特别是从1到100这种需求,这里记录几种shell中从1到100的循环方法   方法 类c语言 for ((i=1; i<=100;  ...

  8. Media Player框架

    导入MediaPlayer.framework框架. //声明一个媒体播放器 var moviePlayer:MPMoviePlayerController? @IBAction func playM ...

  9. socket.io中emit和on的用法【转】

    socket.emit('action');表示发送了一个action命令,命令是字符串的,在另一端接收时,可以这么写: socket.on('action',function(){...});soc ...

  10. Java类加载及实例化的调用顺序

    标题起得略拗口,大概意思就是说在一个Java类中,域和构造方法的调用顺序. 1. 没有继承的情况 单独一个类的场景下,初始化顺序为依次为 静态数据,继承的基类的构造函数,成员变量,被调用的构造函数. ...