抓取策略(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,改变其行为:

...随之,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. 保持默认,同fetch="select",如:
  3. "classes"column="classesid"fetch="select"/>
  4. fetch="select",另外发送一条select语句抓取当前对象关联实体或集合
  5. 设置fetch="join",如:
  6. "classes"column="classesid"fetch="join"/>
  7. fetch="join",hibernate会通过select语句使用外连接来加载其关联实体或集合
  8. 此时lazy会失效
  9. hibernate抓取策略(集合代理的批量抓取)
  10. 保持默认,同fetch="select",如:
  11. "students"inverse="true"cascade="all"fetch="select">
  12. fetch="select",另外发送一条select语句抓取当前对象关联实体或集合
  13. hibernate抓取策略(集合代理的批量抓取)
  14. 设置fetch="join",如:
  15. "students"inverse="true"cascade="all"fetch="join">
  16. fetch="join",hibernate会通过select语句使用外连接来加载其关联实体或集合
  17. 此时lazy会失效
  18. hibernate抓取策略(集合代理的批量抓取)
  19. 设置fetch="subselect",如:
  20. "students"inverse="true"cascade="all"fetch="subselect">
  21. fetch="subselect",另外发送一条select语句抓取在前面查询到的所有实体对象的关联集合
  22. hibernate抓取策略,,batch-szie在<class>上的应用
  23. batch-size属性,可以批量加载实体类,参见:Classes.hbm.xml
  24. <classname="Classes"table="t_classes"batch-size="3">
  25. hibernate抓取策略,batch-szie在集合上的应用
  26. batch-size属性,可以批量加载实体类,参见:Classes.hbm.xml
  27. "students"inverse="true"cascade="all"batch-size="5">

你可能感兴趣的:(java,数据库)