`
JenHui
  • 浏览: 8859 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

Hibernate的抓取策略总结

阅读更多

今天在做hibernate的性能优化的时候,hibernate的抓取策略又派上用场了,于是顺便总结了一下并作了如下记录。
 
hibernate的抓取策略通常有下面四种:

 

     1.连接抓取(Join fetching) ,即Hibernate通过 在select语句使用outer join(外连接)来 获得对象的关联实例或  者关联集合.
 
     2.查询抓取(Select fetching) ,即另外发送一条 select 语句抓取当前对象的关联实体或集合。除非你显式的指定lazy="false"禁止 延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句.
 
     3.子查询抓取(Subselect fetching) ,即 另外发送一条select 语句抓取在前面查询到 的所有实体对象的关联集合。除非你显式的指定lazy="false" 禁止延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条
select语句 .


      4.批量抓取(Batch fetching) ,这种策略跟查询抓取本质上是一样的,只不过是 对查询抓取的优化而已, 通过指定一个主键或外键 列表,Hibernate使用单条select语句获取一批对象实例或集合.

 

 Join fetching , Select fetching 与 Batch-size 可以为单个实体的抓取进 行性能优化;
 Join fetching , Select fetching ,Subselect fetching , Batch fetching 都可以为集合的抓取进行性能优化;
 
下面将以一个多对一双向关联映射(多个员工属于同一部门)进行说明:

 

关联映射后的关系模型:
 t_employee(id int pk, name varchar, departmentid int fk->t_department(id))
 t_department(id int pk, name varchar)
 
实体模型:
 com.lrh.hibernate.Employee(int id, String name, Department department)
 com.lrh.hibernate.Department(int id, String name, Set employees)
 
配置文件:
  <!-- com.lrh.hibernate/Employee.hbm.xml -->
 
  <hibernate-mapping> 
      <class name="com.lrh.hibernate.Employee" table="t_employee"> 
          <id name="id"><generator class="native"/></id> 
          <property name="name"/> 
          <!-- <many-to-one>映射多对一关系 -->
          <many-to-one name="department" column="departmentid"/> 
      </class> 
 </hibernate-mapping>
 
  <!-- com.lrh.hibernate/Department.hbm.xml -->
 
  <hibernate-mapping> 
      <class name="com.lrh.hibernate.Department" table="t_department"> 
          <id name="id"><generator class="native"/></id> 
          <property name="name"/> 
           <!--  双向关联中,为<set>加入”inverse=true”可以反转维护关系:
                 Hibernate将放弃从一的一端维护。也就是employee和department的关系必须使用employee维护,
                              操作department时Hibernate将不维护这个关系。
             -->
          <set name="employees" inverse="true" > 
              <!-- <key>指定引用至自身的外键表(t_employee)中的外键 -->
             <key column="departmentid"/> 
              <!-- <one-to-many>映射一对多关系 -->
              <one-to-many class="com.lrh.hibernate.Employee"/> 
          </set> 
      </class> 
  </hibernate-mapping>

 

 

1.连接抓取(Join fetching)

     连接抓取, 使用连接抓取可以将本来需要查询两次(或多次)表的多次查询 ,现在只需要一次查询即可完成,以上面的关系模型为例,在初始化一个含有一对多关系的 Department 与Employee 的时候, 会先加载Department , 然后再根据Department.id 将对应的Employee 集合初始化, 一般完成初始化需要发送至少两条 SQL 语句, 但如果用 连接抓取, 则会根据需要查询的Department.id, 将 Department 表与 Employee 表连接起来进行查询,仅仅一条 SQL 语句就可以将需要的数据全部加载出来;
             
     使用连接抓取的com.lrh.hibernate/Department.hbm.xml配置文件修改<set></set>节点如下:
    <!--添加fetch="join" -->
    <set name="employees" inverse="true" fetch="join"> 
       <key column="departmentid"/> 
       <one-to-many class="com.lrh.hibernate.Employee"/> 
     </set>  
     测试核心代码:
     Department d = (Department)session.get(Department.class,1); 
     System.out.println(d.getEmployees.size());

 


2.查询抓取(Select fetching)
      查询抓取是在集合抓取的时候使用的默认策略, 即如果集合需要初始化, 那么会重新发出一条 SQL 语句初始化Employee 集合;也就是常说的N+1次查询的查询策略;
          
    使用连接抓取的com.lrh.hibernate/Department.hbm.xml配置文件修改<set></set>节点如下:
    <!--添加fetch="select" -->
    <set name="employees" inverse="true" fetch="select"> 
       <key column="departmentid"/> 
       <one-to-many class="com.lrh.hibernate.Employee"/> 
     </set>  
     测试核心代码:
     Department d = (Department)session.get(Department.class,1); 
     System.out.println(d.getEmployees.size());
   

 

3.子查询抓取(Subselect fetching)

           子查询抓取, 另外发送一条SELECT 语句抓取在前面查询到(或者抓取到)的所有实体对象的关联集合. 还是以上面的关系模型例子 : 如果查询出了3 个 Department 实体,由于开启了懒加载,那么他们的 Employee 都没有被初始化, 那么我现在手动初始化一个Department 的 Employee ,此时由于我选的是 Subselect fetching策略,所以 Hibernate 会将前面查询到的实体对象(3 个 Department)的关联集合(在 <set name="Employee" fetch="subselect" /> )使用一条 Select 语句一次性抓取出来, 这样减少了与数据库的交互次数, 一次将每个对象的集合都给初始化了;subselect 只在 <set> 集合中出现 。
 
  使用连接抓取的com.lrh.hibernate/Department.hbm.xml配置文件修改<set></set>节点如下:
    <!--添加fetch="subselect" -->
    <set name="employees" inverse="true" fetch="subselect"> 
       <key column="departmentid"/> 
       <one-to-many class="com.lrh.hibernate.Employee"/> 
    </set>  
    测试核心代码:
     List results = session.createQuery("From Department d where d.id in (1,2,3)").list(); 
     Department d = (Department)results.get(0); 
     System.out.println(d.getEmployees.size());

 

 

4.批量抓取(Batch fetching)
          批量抓取跟查询抓取本质上是一样的,只不过将一次一条的 查询策略改为一次 N 条的批量 查询; 同样以上面的关系模型为例,我查询出了 3个 Department 实体,Employee 默认开启了懒加载,我们可以如此设置 :

<set name="Employee" fetch="select" batch-size="2" />  当初始化一个 Department 的 Employee 集合的时候, Hibernate 还是发出了一条SQL 语句,跟查询抓取不同的是:这条 SQL 与是通过指定了 Employee 表中的 departmentid 外键列表(2个),Hibernate 会以一条 SQL 语句初始化 batch-size 指定的数量的 Employee 集合;即根据batch-size 分成了两组(一组有2个 Department id 值的列表,第二组只有1个)来初始化 Employee 集合。
 
  使用连接抓取的com.lrh.hibernate/Department.hbm.xml配置文件修改<set></set>节点如下:
    <!--添加fetch="select" batch-size="2"-->
    <set name="employees" inverse="true" fetch="select"  batch-size="2"> 
       <key column="departmentid"/> 
       <one-to-many class="com.lrh.hibernate.Employee"/> 
    </set>  
 
  测试核心代码:
     List results = session.createQuery("From Department d where d.id in (1,2,3)").list(); 
     Department d = (Department)results.get(0); 
     System.out.println(d.getEmployees.size());

 

分享到:
评论

相关推荐

    Hibernate学习总结

    学习成长路,Hibernate总结: 1.Hibernate入门优缺点、 2.Hibernate的操作CRUD、 3.主键生成机制、 4.持久化对象的状态、 ...8.Hibernate检索策略(fetch抓取策略)、 9.二级缓存、 10.Hbernate的检索方式(HQL语句)

    Hibernate+中文文档

    19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-ended association proxies) 19.1.4. 实例化集合和代理(Initializing collections and proxies) 19.1.5. 使用批量抓取(Using...

    hibernate3.2中文文档(chm格式)

    19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-ended association proxies) 19.1.4. 实例化集合和代理(Initializing collections and proxies) 19.1.5. 使用批量抓取(Using...

    HibernateAPI中文版.chm

    19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-ended association proxies) 19.1.4. 实例化集合和代理(Initializing collections and proxies) 19.1.5. 使用批量抓取(Using...

    Hibernate 中文 html 帮助文档

    19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-ended association proxies) 19.1.4. 实例化集合和代理(Initializing collections and proxies) 19.1.5. 使用批量抓取(Using...

    hibernate总结

    Hibernate的检索策略: 1. 延迟检索(加载)映射文件中改变lazy a) Lazy的取值: i. Many-to-one 1. false 2. proxy 3. no-proxy ii. set 一对多 1. true  2. false  3. extra 根据对set容器的不同,可以产生...

    Hibernate中文详细学习文档

    19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-ended association proxies) 19.1.4. 实例化集合和代理(Initializing collections and proxies) 19.1.5. 使用批量抓取(Using...

    hibernate 体系结构与配置 参考文档(html)

    总结 2. 体系结构(Architecture) 2.1. 概况(Overview) 2.2. 实例状态 2.3. JMX整合 2.4. 对JCA的支持 2.5. 上下文相关的(Contextual)Session 3. 配置 3.1. 可编程的配置方式 3.2. 获得SessionFactory ...

    Hibernate教程

    20.1.2. 调整抓取策略(Tuning fetch strategies) 20.1.3. 单端关联代理(Single-ended association proxies) 20.1.4. 实例化集合和代理(Initializing collections and proxies) 20.1.5. 使用批量抓取(Using...

    Hibernate_3.2.0_符合Java习惯的关系数据库持久化

    19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-ended association proxies) 19.1.4. 实例化集合和代理(Initializing collections and proxies) 19.1.5. 使用批量抓取(Using...

    hibernate+中文api

    3.4.2. 外连接抓取(Outer Join Fetching) 3.4.3. 二进制流 (Binary Streams) 3.4.4. 二级缓存与查询缓存 3.4.5. 查询语言中的替换 3.4.6. Hibernate的统计(statistics)机制 3.5. 日志 3.6. 实现NamingStrategy...

    hibernate3.04中文文档.chm

    20.1.2. 调整抓取策略(Tuning fetch strategies) 20.1.3. 单端关联代理(Single-ended association proxies) 20.1.4. 实例化集合和代理(Initializing collections and proxies) 20.1.5. 使用批量抓取...

    Hibernate参考文档

    19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-ended association proxies) 19.1.4. 实例化集合和代理(Initializing collections and proxies) 19.1.5. 使用批量抓取(Using...

    hibernate 框架详解

    目录 前言 1.... 2.... 1. 在Tomcat中快速上手 ... 1.1. 开始Hibernate之旅 1.2.... 1.3.... 1.4.... 调整抓取策略(Tuning fetch strategies) 20.1.3. 单端关联代理(Single-ended association proxies) ...

    Hibernate3的帮助文档

    4.4.2. 外连接抓取(Outer Join Fetching) 4.4.3. 二进制流 (Binary Streams) 4.4.4. 二级缓存与查询缓存 4.4.5. 查询语言中的替换 4.4.6. Hibernate的统计(statistics)机制 4.5. 日志 4.6. 实现NamingStrategy...

    hibernate_reference中文文档.pdf

    1.4. 总结 ................................................................. 25 2. 体系结构(Architecture) ..................................................... 27 2.1. 概况(Overview) .................

    hibernate 帮助文档

    1.4. 总结 ................................................................. 25 2. 体系结构(Architecture) ..................................................... 27 2.1. 概况(Overview) .................

    NHibernate参考文档 2.0.0 chm

    16.1.2. 调整抓取策略(Tuning fetch strategies) 16.1.3. 单端关联代理(Single-ended association proxies) 16.1.4. 初始化集合和代理(Initializing collections and proxies) 16.1.5. 使用批量抓取(Using ...

    NHibernate中文帮组文档(2008.11月更新)

    16.1.2. 调整抓取策略(Tuning fetch strategies) 16.1.3. 单端关联代理(Single-ended association proxies) 16.1.4. 初始化集合和代理(Initializing collections and proxies) 16.1.5. 使用批量抓取(Using ...

    NHibernate中文帮助手册API

     3.5.2 外连接抓取(Outer Join Fetching)  3.5.3. 查询缓存  3.5.4. 查询语言中的替换  3.6. 日志  3.7. 实现NamingStrategy  3.8. XML配置文件  4. 持久化类(Persistent Classes)  4.1. 一个简单的...

Global site tag (gtag.js) - Google Analytics