原文 :http://4045060.blog.51cto.com/4035060/1088025

部分参考:http://www.cnblogs.com/rongxh7/archive/2010/05/12/1733088.html

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

连接抓取(Join fetching) - Hibernate通过 在SELECT语句使用OUTER JOIN 
(外连接)来 获得对象的关联实例或者关联集合.


查询抓取(Select fetching) - 另外发送一条 SELECT 语句抓取当前对象的关联实 
体或集合。除非你显式的指定lazy="false"禁止 延迟抓取(lazy fetching),否 
则只有当你真正访问关联关系的时候,才会执行第二条select语句.

   备注: 查询抓取, 这种策略是在集合抓取的时候的默认策略, 即如果集合需要初始化, 那么会重新发出一条 SQL 语句进行查询;

        这是集合默认的抓取策略, 也就是我们常会出现N+1次查询的查询策略;


子查询抓取(Subselect fetching) - 另外发送一条SELECT 语句抓取在前面查询到 
(或者抓取到)的所有实体对象的关联集合。除非你显式的指定lazy="false" 禁止延迟 
抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条 
select语句


批量抓取(Batch fetching) - 对查询抓取的优化方案, 通过指定一个主键或外键 
列表,Hibernate使用单条SELECT语句获取一批对象实例或集合

一、hibernate抓取策略(单端代理的批量抓取fetch=select(默认)/join)

1)保持默认,同fetch="select"

<many-to-one name="group" column="group_id" fetch="select" />

另外发送一条select语句抓取当前对象关联实体或集合.

测试代码

        Session session = null;
try {
session = HibernateUtils.getSession();
/**
* 只读操作,不使用事务也可进行.Hibernate建议任何操作都使用事务.
*/
User u = (User) session.load(User.class,"402881e6466ae95a01466ae95c4d0004");// 加载User
System.out.println("执行了session.load方法");
System.out.println("[value]" + u.getName());
System.out.println("[value]" + u.getGroup().getName());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (session != null) {
// 关闭session
session.close();
}
}

 执行效果

执行了session.load方法
Hibernate:
select
user0_.id as id0_0_,
user0_.name as name0_0_,
user0_.password as password0_0_,
user0_.createTime as createTime0_0_,
user0_.updateTime as updateTime0_0_,
user0_.group_id as group6_0_0_
from
TEST_User user0_
where
user0_.id=?
[value]james
Hibernate:
select
group0_.id as id1_0_,
group0_.name as name1_0_
from
TEST_Group group0_
where
group0_.id=?
[value]集团2

2)设置fetch="join"

<many-to-one name="group" column="group_id" fetch="join" />

hibernate会通过select语句使用外连接来加载其关联实体或集合. 此时lazy会失效.  执行结果:一条join语句

测试代码同上

执行效果

执行了session.load方法
Hibernate:
select
user0_.id as id0_1_,
user0_.name as name0_1_,
user0_.password as password0_1_,
user0_.createTime as createTime0_1_,
user0_.updateTime as updateTime0_1_,
user0_.group_id as group6_0_1_,
group1_.id as id1_0_,
group1_.name as name1_0_
from
TEST_User user0_
left outer join
TEST_Group group1_
on user0_.group_id=group1_.id
where
user0_.id=?
[value]james
[value]集团2

二、hibernate抓取策略(集合代理的批量抓取,fetch=select(默认)/join/subselect)

1)保持默认,同fetch="select",如

<set name="users" fetch="select" >
   <key column="group_id"/>
   <one-to-many class="com.test.entity.User" />
  </set>fetch="select",

另外发送一条select语句抓取当前对象关联实体或集合
测试结果:2条独立的查询语句

 测试代码

Session session = null;
try {
session = HibernateUtils.getSession();
/**
* 只读操作,不使用事务也可进行.Hibernate建议任何操作都使用事务.
*/
Group g = (Group) session.load(Group.class,"402881e6466ae95a01466ae95c460001");// 加载Group
System.out.println("执行了session.load方法");
System.out.println("[value]" + g.getName());
Set<User> us = g.getUsers();
for (Iterator iter = us.iterator(); iter.hasNext();) {
User u = (User) iter.next();
System.out.println("[value]" + u.getName());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (session != null) {
// 关闭session
session.close();
}
}

执行效果

执行了session.load方法
Hibernate:
select
group0_.id as id1_0_,
group0_.name as name1_0_
from
TEST_Group group0_
where
group0_.id=?
[value]集团2
Hibernate:
select
users0_.group_id as group6_1_,
users0_.id as id1_,
users0_.id as id0_0_,
users0_.name as name0_0_,
users0_.password as password0_0_,
users0_.createTime as createTime0_0_,
users0_.updateTime as updateTime0_0_,
users0_.group_id as group6_0_0_
from
TEST_User users0_
where
users0_.group_id=?
[value]james
[value]kobe
[value]jordan

2)设置fetch="join"

如:

<set name="users" fetch="join" >
   <key column="group_id"/>
   <one-to-many class="com.test.entity.User" />
  </set>

fetch="join",hibernate会通过select语句使用外连接来加载其关联实体或集合. 此时lazy会失效
测试结果:1条独立的join查询语句

测试代码: 同上例

执行效果:

Hibernate:
select
group0_.id as id1_1_,
group0_.name as name1_1_,
users1_.group_id as group6_3_,
users1_.id as id3_,
users1_.id as id0_0_,
users1_.name as name0_0_,
users1_.password as password0_0_,
users1_.createTime as createTime0_0_,
users1_.updateTime as updateTime0_0_,
users1_.group_id as group6_0_0_
from
TEST_Group group0_
left outer join
TEST_User users1_
on group0_.id=users1_.group_id
where
group0_.id=?
[value]集团2
[value]james
[value]jordan
[value]kobe

3)设置fetch="subselect"

<set name="users" fetch="subselect" >
   <key column="group_id"/>
   <one-to-many class="com.test.entity.User" />
  </set>

测试结果: fetch="subselect",另外发送一条select语句抓取在前面查询到的所有实体对象的关联集合.

测试代码: 同上例

执行效果:

执行了session.load方法
Hibernate:
select
group0_.id as id1_0_,
group0_.name as name1_0_
from
TEST_Group group0_
where
group0_.id=?
[value]集团2
Hibernate:
select
users0_.group_id as group6_1_,
users0_.id as id1_,
users0_.id as id0_0_,
users0_.name as name0_0_,
users0_.password as password0_0_,
users0_.createTime as createTime0_0_,
users0_.updateTime as updateTime0_0_,
users0_.group_id as group6_0_0_
from
TEST_User users0_
where
users0_.group_id=?
[value]kobe
[value]jordan
[value]james

为更好体现subselect的效果用例如下: 通过调节获取符合条件的Group集合,访问其中一个Group的关联集合User

测试代码:

List<Group> gs=session.createQuery(" from Group g where g.name like'集团%'").list();
Group g0=gs.get(0);
System.out.println("[value]" + g0.getName());
System.out.println("[value]" + g0.getUsers().size());

执行效果: 在之前查询语句的基础上,发出子查询.

Hibernate:
select
group0_.id as id1_,
group0_.name as name1_
from
TEST_Group group0_
where
group0_.name like '集团%'
[value]集团2
Hibernate:
select
users0_.group_id as group6_1_,
users0_.id as id1_,
users0_.id as id0_0_,
users0_.name as name0_0_,
users0_.password as password0_0_,
users0_.createTime as createTime0_0_,
users0_.updateTime as updateTime0_0_,
users0_.group_id as group6_0_0_
from
TEST_User users0_
where
users0_.group_id in (
select
group0_.id
from
TEST_Group group0_
where
group0_.name like '集团%'
)
[value]3

若将fetch="subselect"的配置去掉.

则执行效果如下 , 用了默认的select fetch查询方式

Hibernate:
select
group0_.id as id1_,
group0_.name as name1_
from
TEST_Group group0_
where
group0_.name like '集团%'
[value]集团2
Hibernate:
select
users0_.group_id as group6_1_,
users0_.id as id1_,
users0_.id as id0_0_,
users0_.name as name0_0_,
users0_.password as password0_0_,
users0_.createTime as createTime0_0_,
users0_.updateTime as updateTime0_0_,
users0_.group_id as group6_0_0_
from
TEST_User users0_
where
users0_.group_id=?
[value]3

总结:


 hibernate抓取策略

1.单端代理的批量抓取 (如Group.getUser().getName()这样)
 1.1 保持默认,同fetch="select",如:<many-to-one name="classes" column="classesid" fetch="select"/>
   fetch="select", 有用到lazy, 实际用到关联属性才会发出SQL.(另外发送一条select语句抓取当前对象关联实体或集合)
   1.2设置fetch="join",如:<many-to-one name="classes" column="classesid" fetch="join"/>
    fetch="join",hibernate会通过select语句使用外连接来加载其关联实体或集合. 只发出1条SQL.
    此时lazy会失效

2.集合代理的批量抓取 (如Set<User> us=Group.getUsers();  然后获取集合中User的属性)
 2.1 保持默认,同fetch="select",如:<set name="students" inverse="true" cascade="all" fetch="select">
     fetch="select",另外发送一条select语句抓取当前对象关联实体或集合
  2.2  设置fetch="join",如:<set name="students" inverse="true" cascade="all" fetch="join">
    fetch="join", 有用到lazy, 实际用到关联属性才会发出SQL.( hibernate会通过select语句使用外连接来加载其关联实体或集合)
   此时lazy会失效

2.3设置fetch="subselect",如:<set name="students" inverse="true" cascade="all" fetch="subselect">
   fetch="subselect",另外发送一条select语句抓取在前面查询到的所有实体对象的关联集合
 
3.hibernate批量抓取,Hibernate提供了两种批量抓取方案:类级别和集合级别。

类级别的批量查询。如果一个Session中需要载入30个student实例,在student中拥有一个成员变量class,该class执行Class对象。如果lazy=“true”,如果们需要变量整个student集合,每一个student都需要getClass(),hibernate在默认情况下回执行30次select查询语句,得到Class对象。这个时候可以通过在映射文件的Class属性,batch-size。

  1. <class name=”Class” batch-size=”15”>….</class>

这样Hibernate将只需要执行两次查询即可:15,15。

集合级别的批量查询。如果我们需要遍历Class所拥有的所有Student对象,在Session中需要载入30个Class对象,遍历Class集合将会引起30次Select查询,每次查询都会调用getStudents()。如果在Class的映射定义中,允许对Students进行批量抓取,则Hibernate就会预先加载整个集合。

  1. <set name=”students” batch-size=”15”>…</set>

Hibernate 抓取策略fetch-1 (select join subselect)的更多相关文章

  1. 029 hibernate抓取策略

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

  2. hibernate抓取策略

    抓取策略(fetching strategy) 是指:当应用程序需要在(Hibernate实体对象图的)关联关系间进行导航的时候, Hibernate如何获取关联对象的策略.抓取策略可以在O/R映射的 ...

  3. Hibernate之加载策略(延迟加载与即时加载)和抓取策略(fetch)

    假设现在有Book和Category两张表,表的关系为双向的一对多,表结构如下: 假设现在我想查询id为2的那本书的书名,使用session.get(...)方法: Session session=H ...

  4. Hibernate 抓取策略

    抓取策略: 为了改变SQL语句执行的方式 当应用程序需要在Hibernate实体对象的关联关系间进行导航的时候,Hibernate如何获取关联对象的策略 抓取策略可以在O/R映射的元数据中声明,也可以 ...

  5. Hibernate 抓取策略fetch-2 (批量抓取batch-size以及hibernate.jdbc.fetch_size、hibernate.jdbc.batch_size)

    类关系: User N~1 Group 测试代码: System.out.println("1"); List stuList = session.createQuery(&quo ...

  6. 【Java EE 学习 48】【Hibernate学习第五天】【抓取策略】【二级缓存】【HQL】

    一.抓取策略. 1.hibernate中提供了三种抓取策略. (1)连接抓取(Join Fetch):这种抓取方式是默认的抓取方式.使用这种抓取方式hibernate会在select中内连接的方式获取 ...

  7. 【Hibernate 8】Hibernate的调优方法:抓取策略

    在上一篇博客中,介绍了Hibernate的缓存机制.合理的配置缓存,可以极大程度上优化Hibernate的性能.这篇博客,介绍另外一个调优方式:抓取策略. 一.什么是抓取策略 抓取策略(fetchin ...

  8. Hibernate中的多表查询及抓取策略

    1.Hibernate中的多表查询 1.1SQL中的多表查询 [交叉连接] select * from A,B; [内连接] 显示内连接:inner join(inner 可以省略) Select * ...

  9. Hibernate框架笔记04HQL_QBC查询详解_抓取策略优化机制

    目录 1. Hibernate的查询方式 1.1 方式一:OID查询 1.2 方式二:对象导航查询 1.3 方式三:HQL方式 1.4 方式四:QBC查询 1.5 方式五:SQL查询 2. 环境搭建 ...

随机推荐

  1. 转:服务器控件的 ID,ClientID,UniqueID 的区别

    动态加载用户控件的怪问题 动态加载用户控件的时候,会因为调用一些控件的一些属性和方法而造成控件命名混乱. 因为add 一个用户控件或者 loadcontrol 的时候 如果没有指定控件的id,clie ...

  2. 初探Openstack Neutron DVR

    目前在Juno版本的trunk中已经合入了DVR相关的代码,我的理解是在Juno版本中DVR是一个experimental feature.最好需要稳定一个版本以后再上生产环境.之前写过一篇博文是DV ...

  3. R处理xml文件

    最近处理数据的时候需要处理一些xml文件,但是xml文件的格式之前并不是很熟悉.幸好R有一些函数可以帮助快速处理xml文件.其中的xmlToList函数尤其方便,可以使你从陌生的XML迅速回到熟悉的R ...

  4. 无法Ping通windows 7主机

    今天在使用Filezilla FTP_SERVER新建了一个windows主机上的FTP服务器. 建立完成之后,从MAC上无法进行连接也甚至连主机也无法连接,怀疑是防火墙的问题. 网上一搜确实是,但是 ...

  5. ZOJ Problem Set - 3643 Keep Deleting

    题目大意: 给出a和b串,a是b串的子串,如果b串有连续的a串,那么就将b串的a串删除,问删除多少次: 题目分析: 打比赛的时候没敲出来,后来想到用栈的思想去模拟就行,网上还有用KMP+栈去做的,没有 ...

  6. CentOS 6.2 OpenVPN 搭建

    一.yum 安装. 二.下载 easy-rsa 3.0 三.生成根证书.服务器.客户端证书.ta 生成流程: wget -c https://github.com/OpenVPN/easy-rsa/a ...

  7. 移动开发中使用Onsen UI的笔记

    onsen var m_index = ons.bootstrap() 初始化框架 m_index 赋值 增加对象. m_index.value('getUser',{ // user:window. ...

  8. JavaWeb学习记录(九)——Cookie的增加、删除、查看

    一.servlet功能代码: public void doGet(HttpServletRequest request, HttpServletResponse response)           ...

  9. 20145220&20145209&20145309信息安全系统设计基础实验报告(1)

    实验贡献:韩旭飞 刘一阳 李昊实验报告贡献:李昊 刘一阳 韩旭飞 PART1 一.实验原理 交叉编译,简单地说,就是在一个平台上生成另一个平台上的可执行代码.同一个体系结构可以运行不同的操作系统:同样 ...

  10. Hadoop集群添加新节点步骤

    1.在新节点中进行操作系统配置,包括主机名.网络.防火墙和无密码登录等. 2.在所有节点/etc/host文件中添加新节点 3.把namenode的有关配置文件复制到该节点 4.修改master节点s ...