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. Linux的read命令

    对于写bash脚本的朋友,read命令是不可或缺的,需要实践一下就可以了解read命令的大致用途: 编写一个脚本: #!/bin/bash # hao32 test read echo -e &quo ...

  2. centos6.4 yum kvm

    1. 安装软件包:   yum -y install virt-manager; yum install qemu-kvm  yum install libvirt yum install libvi ...

  3. 杀死当前Excel进程

    说明: 代码编写过程中,有时需要杀死当前Excel进程,而不影响其他Excel进程. 代码如下: 添加引用: //杀死当前进程的API引用 using System.Runtime.InteropSe ...

  4. TDD中的迭代

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:TDD中的迭代.

  5. unity3d 获取相机视口四个角的坐标

    功能:如标题所示,主要考虑用来做3d Plane的自适应屏幕 /// <summary> /// 获取指定距离下相机视口四个角的坐标 /// </summary> /// &l ...

  6. 【JavaScript】出现即使设置了ID也获取不到的可能原因与window.onload

    有时候.在JavaScript中.即使设置了ID也有可能出现document.getElementById()获取不到的情况,然后你就開始想document是否写错之类的.事实上根本就不是你的代码的大 ...

  7. iOS开发之蓝牙通信

    一.引言 蓝牙是设备近距离通信的一种方便手段,在iPhone引入蓝牙4.0后,设备之间的通讯变得更加简单.相关的蓝牙操作由专门的 CoreBluetooth.framework进行统一管理.通过蓝牙进 ...

  8. Qt树形控件QTreeView使用1——节点的添加删除操作 复选框的设置

    QtreeView是ui中最常用的控件,Qt中QTreeWidget比QTreeView更简单,但没有QTreeView那么灵活(QTreeWidget封装的和MFC的CTreeCtrl很类似,没有m ...

  9. yum在线升级

    RPM优点 由於 RPM 是透过预先编译并打包成为 RPM 文件格式后,再加以安装的一种方式,并且还能够进行数据库的记载. 所以 RPM 有以下的优点: RPM 内含已经编译过的程序与配置档等数据,可 ...

  10. 使用Netty进行Android与Server端通信实现文字发送接收与图片上传

    ANOTHER TITLE: Let’s use netty to achieve text send and receive and  image transfer to server based ...