抓取策略(Fetching strategies)

转自:http://sishuok.com/forum/blogPost/list/3805.html

实例A引用实例B,B如果是代理的话(比如多对一关联中):如果遍历A的查询结果集(假设有10条记录),在遍历A的时候,访问B变量,将会导致n次查询语句的发出!这个时候,如果在B一端的class上配置batch-size,hibernate将会减少SQL语句的数量。

     Hibernate可以充分有效的使用批量抓取,也就是说,如果仅一个访问代理(或集合),那么hibernate将不载入其他未实例化代理。批量抓取是延迟查询抓取的优化方案,你可以在两种批量抓取方案之间进行选择:在类级别和集合级别。

     类/实体级别的批量抓取很容易理解,假设你在运行时将需要面对下面的问题:你在一个Session中载入了25个Cat实例,每个Cat实例都拥有一个引用成员owner,其指向Persion,而Persion类是代理,同时lazy=true,如果你必须遍历整修cats集合,对每个元素调用getOwner()方法,hibernate将会默认的执行25次SELECT查询,得到其ower的代理对象。这时你可以通过在映射文件的Person属性,显式声明batch-size,改变其行为:

     <class name=”Person” batch-size=”10”>...</class>随之,hibernate将只需要执行三次查询,分别是10,10,5.

抓取策略(fetching strategy) 是指:当应用程序需要在(Hibernate实体对象图的)关联关系间进行导航的时候, Hibernate如何获取关联对象的策略。抓取策略可以在O/R映射的元数据中声明,也可以在特定的HQL 或条件查询(Criteria Query)中重载声明。

Hibernate3 定义了如下几种抓取策略:

  • 连接抓取(Join fetching) - Hibernate通过 在SELECT语句使用OUTER JOIN(外连接)来 获得对象的关联实例或者关联集合。
  • 查询抓取(Select fetching) -另外发送一条 SELECT 语句抓取当前对象的关联实体或集合。除非你显式的指定lazy="false"禁止 延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。
  • 子查询抓取(Subselect fetching) - 另外发送一条SELECT 语句抓取在前面查询到(或者抓取到)的所有实体对象的关联集合。除非你显式的指定lazy="false" 禁止延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。
  • 批量抓取(Batch fetching) - 对查询抓取的优化方案, 通过指定一个主键或外键列表,Hibernate使用单条SELECT语句获取一批对象实例或集合。

Hibernate会区分下列各种情况:

  • Immediate fetching,立即抓取 - 当宿主被加载时,关联、集合或属性被立即抓取。
  • Lazy collection fetching,延迟集合抓取- 直到应用程序对集合进行了一次操作时,集合才被抓取。(对集合而言这是默认行为。)
  • "Extra-lazy" collection fetching,"Extra-lazy"集合抓取 -对集合类中的每个元素而言,都是直到需要时才去访问数据库。除非绝对必要,Hibernate不会试图去把整个集合都抓取到内存里来(适用于非常大的集合)。
  • Proxy fetching,代理抓取 - 对返回单值的关联而言,当其某个方法被调用,而非对其关键字进行get操作时才抓取。
  • "No-proxy" fetching,非代理抓取 - 对返回单值的关联而言,当实例变量被访问的时候进行抓取。与上面的代理抓取相比,这种方法没有那么“延迟”得厉害(就算只访问标识符,也会导致关联抓取)但是更加透明,因为对应用程序来说,不再看到proxy。这种方法需要在编译期间进行字节码增强操作,因此很少需要用到。
  • Lazy attribute fetching,属性延迟加载 - 对属性或返回单值的关联而言,当其实例变量被访问的时候进行抓取。需要编译期字节码强化,因此这一方法很少是必要的。

这里有两个正交的概念:关联何时被抓取,以及被如何抓取(会采用什么样的SQL语句)。不要混淆它们!我们使用抓取来改善性能。我们使用延迟来定义一些契约,对某特定类的某个脱管的实例,知道有哪些数据是可以使用的。

 

java代码:
  1. hibernate抓取策略(单端代理的批量抓取)  
  2.   
  3.    
  4.   
  5. 保持默认,同fetch="select",如:  
  6.   
  7. <many-to-one name="classes" column="classesid" fetch="select"/>  
  8.   
  9.    
  10.   
  11. fetch="select",另外发送一条select语句抓取当前对象关联实体或集合  
  12.   
  13.    
  14.   
  15. 设置fetch="join",如:  
  16.   
  17. <many-to-one name="classes" column="classesid" fetch="join"/>  
  18.   
  19.    
  20.   
  21. fetch="join",hibernate会通过select语句使用外连接来加载其关联实体或集合  
  22.   
  23.    
  24.   
  25. 此时lazy会失效  
  26.   
  27.    
  28.   
  29.    
  30.   
  31. hibernate抓取策略(集合代理的批量抓取)  
  32.   
  33.    
  34.   
  35. 保持默认,同fetch="select",如:  
  36.   
  37. <set name="students" inverse="true" cascade="all" fetch="select">  
  38.   
  39.    
  40.   
  41. fetch="select",另外发送一条select语句抓取当前对象关联实体或集合  
  42.   
  43.    
  44.   
  45. hibernate抓取策略(集合代理的批量抓取)  
  46.   
  47.    
  48.   
  49. 设置fetch="join",如:  
  50.   
  51. <set name="students" inverse="true" cascade="all" fetch="join">  
  52.   
  53.    
  54.   
  55. fetch="join",hibernate会通过select语句使用外连接来加载其关联实体或集合  
  56.   
  57.    
  58.   
  59. 此时lazy会失效  
  60.   
  61.    
  62.   
  63. hibernate抓取策略(集合代理的批量抓取)  
  64.   
  65.    
  66.   
  67. 设置fetch="subselect",如:  
  68.   
  69. <set name="students" inverse="true" cascade="all" fetch="subselect">  
  70.   
  71.    
  72.   
  73. fetch="subselect",另外发送一条select语句抓取在前面查询到的所有实体对象的关联集合  
  74.   
  75.    
  76.   
  77. hibernate抓取策略,,batch-szie在<class>上的应用  
  78.   
  79.    
  80.   
  81. batch-size属性,可以批量加载实体类,参见:Classes.hbm.xml  
  82.   
  83. <class name="Classes" table="t_classes" batch-size="3">  
  84.   
  85.    
  86.   
  87. hibernate抓取策略,batch-szie在集合上的应用  
  88.   
  89.    
  90.   
  91.    
  92.   
  93. batch-size属性,可以批量加载实体类,参见:Classes.hbm.xml  
  94.   
  95. <set name="students" inverse="true" cascade="all" batch-size="5">  

posted @ 2012-05-06 13:58  hibernate3例子  阅读(345)  评论(0编辑  收藏  举报