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. centos git版本服务器配置

    在服务器上安装git及做些操作 - 执行命令 ` sudo yum install curl-devel expat-devel gettext-devel openssl-devel zlib-de ...

  2. Oracle数据库字符串连接方法

    转至:http://database.51cto.com/art/201011/232267.htm 和其他数据库系统类似,Oracle字符串连接使用“||”进行字符串拼接,其使用方式和MSSQLSe ...

  3. 一步一步学android控件(之十六)—— CheckBox

    根据使用场景不同,有时候使用系统默认的CheckBox样式就可以了,但是有时候就需要自定义CheckBox的样式.今天主要学习如何自定义CheckBox样式.在CheckBox状态改变时有时需要做一些 ...

  4. 什么时候应该使用C#的属性

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:什么时候应该使用C#的属性.

  5. spring boot 数据库连接池配置

    HikariCP 连接池配置: http://stackoverflow.com/questions/29650501/hikaricp-starts-when-mvn-spring-bootrun- ...

  6. HTML---Android与js交互实例

    Android 中可以通过webview来实现和js的交互,在程序中调用js代码,只需要将webview控件的支持js的属性设置为true Android(Java)与JavaScript(HTML) ...

  7. IOS 中runtime 不可变数组__NSArray0 和__NSArrayI

    IOS 中runtime 不可变数组__NSArray0 和__NSArrayI 大家可能都遇到过项目中不可变数组避免数组越界的处理:runtime,然而有时候并不能解决所有的问题,因为类簇不一样 # ...

  8. Integer Inquiry_hdu_1047(大数).java

    Integer Inquiry Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  9. 蘑菇街IM

    https://github.com/mogutt TTServer 蘑菇街TeamTalk之消息服务器 Updated 2 days ago   Shell 122 208 TTAutoDeploy ...

  10. 【Android】BroadCast广播机制应用与实例

    如何编写广播接收器 第一步:需要继承BroadcastReceiver类,覆写其中的onReceive()方法. class MyBroadcastReceiver extends Broadcast ...