Hibernate检索策略

检索策略追求的两个目标是:(以客户和订单的例子说明)

  • 不浪费内存:当Hibernate从数据库中加载Customer对象时,如果同时加载所有关联的Order对象,而程序实际上仅仅需要访问Customer对象,那么这些关联的Order对象就白白浪费了许多内存。
  • 更高的查询效率:发送尽可能少的SQL语句。

类级别的检索策略

  类级别可选的检索策略包括立即检索和延迟检索,默认为延迟检索。
  立即检索: 立即加载检索方法指定的对象。
  延迟检索: 延迟加载检索方法指定的对象。在使用具体的属性时,再进行加载。
  类级别的检索策略可以通过在映射文件中的<class>元素的lazy属性进行设置,默认为true。
  如果程序加载一个对象的目的是为了访问它的属性,可以采取立即检索。
  如果程序加载一个持久化对象的目的是仅仅为了获得它的引用,可以采用延迟检索。注意延迟检索可能会出现懒加载异常。
  无论<class>元素的lazy属性是true还是false, 仅是只对Session的load方法起作用,因为Session的get方法及Query的list方法在类级别总是使用立即检索策略。若<class>元素的lazy属性为true或取默认值,Session的load()方法不会执行查询数据表的SELECT语句,仅返回代理类对象的实例,该代理类实例有如下特征:

  1. 由Hibernate 在运行时采用CGLIB工具动态生成;
  2. Hibernate创建代理类实例时,仅初始化其 OID 属性;
  3. 在应用程序第一次访问代理类实例的非OID属性时,Hibernate 会初始化代理类实例。

     

一对多和多对多的检索策略

  在映射文件中,用<set>元素来配置一对多关联及多对多关联关系,<set>元素有下面三个属性。
lazy属性:主要决定orders集合被初始化的时机。即到底是在加载Customer对象时就被初始化,还是在程序访问orders集合时被初始化。
batch-size属性:用来为延迟检索策略或立即检索策略设定批量检索的数量。批量检索能减少SELECT语句的数目,提高延迟检索或立即检索的运行性能。
fetch属性:
  若取值为”select”或”subselect”,用来指定初始化orders的查询语句的形式,当fetch属性为”subselect”时,假定Session缓存中有n个orders集合代理类实例没有被初始化,Hibernate能够通过带子查询的select语句,来批量初始化n个orders集合代理类实例,此时,batch-size属性将被忽略,子查询中的select语句为查询CUSTOMERS表OID的SELECT语句。
  若取值为”join”,则指定orders集合被初始化的时机。若把fetch设置为 “join”,则在检索Customer对象时,会采用迫切左外连接策略来检索所有关联的Order对象,此时,lazy属性将被忽略。迫切左外连接检索策略的优点在于使用更少的select语句。注意,Query的list方法会忽略映射文件中配置的迫切左外连接检索策略,而依旧采用延迟加载策略。

lazy属性和fetch属性的可能组合如下图所示:

image_1b3bqsmcrqsg1ndfvpm1s4uah9.png-196.8kB

关于延迟检索和增强延迟检索:

  • 延迟检索(lazy属性值为true)集合属性时,Hibernate在以下情况下初始化集合代理类实例:
    1. 应用程序第一次调用集合的iterator(),size(),isEmpty(), contains()等方法访问集合的属性时。
    2. 通过Hibernate.initialize()静态方法显式初始化时。
  • 增强延迟检索(lazy属性为extra),与lazy=”true”类似,主要区别是增强延迟检索策略能进一步延迟 Customer对象的orders集合代理实例的初始化时机:
    1. 当程序第一次访问orders属性的iterator()方法来遍历元素时,会导致orders集合代理类实例的初始化。
    2. 当程序第一次访问order属性的size(),contains()和isEmpty()方法时,Hibernate不会初始化orders集合类的实例,仅通过特定的select语句查询必要的信息,而不会检索所有的Order对象。

多对一和一对一关联的检索策略

  和<set>一样,<many-to-one>节点也有一个lazy属性和一个fetch属性,如下图所示:
  image_1b3brrg3o1oqg5m11irogui1i1mm.png-89.4kB
  
  且同上述一样,若fetch设为join,那么lazy属性将被忽略。
  
下面总结一下各种检索策略:
 
image_1b3bs3qahkeubm539c1fe51cli13.png-180.4kB