hibernate抓取策略学习

一、hibernate抓取策略概述

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

需要注意的是:hibernate的抓取策略只影响get load 方法,对hql是不影响的。

二、hibernate 抓取策略分类

hibernate有如下四种原生态的Hibernate抓取策略,分别是:select fetching ,join fetching,subselect fetching,Batch fetching。

接下来,我们来详细看一下每种策略的实现

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

代码如下:

       <span style="font-family:KaiTi_GB2312;font-size:18px;"> Student student = (Student)session.get(Student.class, 1);
	System.out.println(student.getName());
	System.out.println(student.getClasses().getName());</span>

配置如下:

<many-to-one name="classes" column="classesid" fetch="select"/>

执行结果:2条语句

Hibernate: select student0_.id as id1_0_, student0_.name as name1_0_, student0_.class_id as class3_1_0_ from student_join student0_ where student0_.id=?

学生1

Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from classes_join classes0_ where classes0_.id=?

高一(1)班

2、连接抓取(Join fetching)

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

配置如下:

<many-to-one name="classes" column="classesid" fetch="join"/>

执行结果:

fetch="join",hibernate会通过select语句使用外连接来加载其关联实体或集合,

此时lazy会失效,

一条join语句:

Hibernate: select student0_.id as id1_1_, student0_.name as name1_1_, student0_.class_id as class3_1_1_, classes1_.id as id0_0_, classes1_.name as name0_0_ from student_join student0_ left outer join classes_join classes1_ on student0_.class_id=classes1_.id
where student0_.id=?

学生1

高一(1)班

如果在配置中在添加一个非空属性,连接就成内连接了:

3、子查询抓取(Subselect fetching)

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

配置文件:

<set name="students" inverse="true" fetch="subselect">

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

访问代码如下:

        <span style="font-family:KaiTi_GB2312;font-size:18px;"> List classList = session.createQuery("from Classes where id in (1,2,3)").list();
			for(Iterator iter = classList.iterator(); iter.hasNext();){
			    Classes c = (Classes)iter.next();
			    System.out.println("Class.name=" + c.getName());
			    Set stuSet = c.getStudents();
			    System.out.println(stuSet.size());
			    if(stuSet != null && !stuSet.isEmpty()){
			       for(Iterator it = stuSet.iterator(); it.hasNext();){
			          Student s = (Student) it.next();
			          System.out.println("student.name=" + s.getName());
			       }
			    }</span>
			}

执行结果:

当不设fetch="subselect" ,即:<set name="students" inverse="true">,结果如下:

执行了3条查询语句

Hibernate: select classes0_.id as id0_, classes0_.name as name0_ from classes_join classes0_  where classes0_.id in (1 , 2 , 3)

Class.name=高一(1)班

Hibernate: select students0_.class_id as class3_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student_join students0_ where students0_.class_id=?

3

student.name=学生4

student.name=学生6

student.name=学生2

Class.name=高一(2)班

Hibernate: select students0_.class_id as class3_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student_join students0_ where students0_.class_id=?

4

student.name=学生3

student.name=学生4

student.name=学生1

student.name=学生2

Class.name=高一(3)班

Hibernate: select students0_.class_id as class3_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student_join students0_ where students0_.class_id=?

0

当设fetch="subselect" ,即:<set name="students" inverse="true" fetch="subselect">,结果如下:

执行了1条查询语句(嵌套子查询)

Hibernate: select classes0_.id as id0_, classes0_.name as name0_ from classes_join classes0_ where classes0_.id in (1 , 2 , 3)

Class.name=高一(1)班

Hibernate: select students0_.class_id as class3_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student_join students0_ where students0_.class_id in (select classes0_.id from classes_join
classes0_ where classes0_.id in (1 , 2 , 3))

4、批量抓取(Batch fetching)

对查询抓取的优化方案, 通过指定一个主键或外键列表,Hibernate使用单条SELECT语句获取一批对象实例或集合。如果我们不使用hibernate的抓取策略,那么代码如下:

但是可以发现这里有一个问题就是“N+1”问题。我们会发出N多条sql语句,怎么解决问题呢?

在 class 上使用batch-size

batch-size属性,可以批量加载实体类。<class name="Classes" table="t_classes" batch-size="3">

当查classes对象时发出9条hql语句配置过后batch-size=3后会之发9/3=3条hql语句,提高性能。

具体效果如下:

在集合上使用

以上是在class上使用,batch-size还可以在集合上使用:batch-size属性,可以批量加载实体类,<set name="students" inverse="true" cascade="all" batch-size="5">

当查students对象时发出10条hql语句配置过后batch-size=5后会之发10/5=2条hql语句,提高性能

三、总结

四种抓取策略说明完了, 咱们来宏观一下, 通过例子可以看出, 这四种抓取策略并不是所有的情况都合适的, 例如, 如果我需要初始化的是一个单独的实体, 那么 subselect 对其就没有效果,因为其本身就只需要查询一个对象, 所以 我们可以对hibernate分成如下两类:单端代理抓取和集合抓取。

单端代理抓取可以使用:Join fetching , Select fetching 与 Batch-size ,可以为单个实体的抓取进    行性能优化;

集合抓取: Join fetching , Select fetching ,Subselect fetching , Batch fetching,可以为集合的抓取进行性能优化;

时间: 2024-10-10 03:17:48

hibernate抓取策略学习的相关文章

029 hibernate抓取策略

实例A引用实例B,B如果是代理的话(比如多对一关联中):如果遍历A的查询结果集(假设有10条记录),在遍历A的时候,访问B变量,将会导致n次查询语句的发出!这个时候,如果在B一端的class上配置batch-size,hibernate将会减少SQL语句的数量. Hibernate可以充分有效的使用批量抓取,也就是说,如果仅一个访问代理(或集合),那么hibernate将不载入其他未实例化代理.批量抓取是延迟查询抓取的优化方案,你可以在两种批量抓取方案之间进行选择:在类级别和集合级别. 类/实体

hibernate抓取策略

18.抓取策略 抓取策略的意思是,在hibernate中,由一个对象如何获取其关联对象的策略,抓取策略是一种优化方式 <set name="students"  lazy="false"  cascasd="save-update"  inverse="false" fetch="select"> 抓取策略: 1.研究的主要是set集合如何提取数据 2.在Classes.hbm.xml文件中 &

Hibernate 优化技术之抓取策略(Fetching strategies)

一.前言 转载请标明出处:http://blog.csdn.net/wlwlwlwl015/article/details/42705585 使用hibernate一年多了,一直觉得他是一个很好用的持久层框架,在处理含有多个复杂的关联关系的数据表时,hibernate提供的各种关联映射可以让我们用少量的代码快速.便捷的去维护各种外键关系,当然他的核心还是允许我们以"面向对象"的方式去操作数据表,因为我们的Java语言就是面向对象的,所以我们使用ORM的持久层框架应该更容易理解和上手,他

Hibernate学习---第十一节:Hibernate之数据抓取策略&amp;批量抓取

1.hibernate 也可以通过标准的 SQL 进行查询 (1).将SQL查询写在 java 代码中 /** * 查询所有 */ @Test public void testQuery(){ // 基于标准的 sql 语句查询 String sql = "select * from t_person"; // 通过 createSQLQuery 获取 SQLQuery,而 SQLQuer 是 Query的子类 SQLQuery query = session.createSQLQue

Hibernate学习笔记(八) — 懒加载与抓取策略

懒加载(Load On Demand)是一种独特而又强大的数据获取方法,它能够在用户滚动页面的时候自动获取更多的数据,而新得到的数据不会影响原有数据的显示,同时最大程度上减少服务器端的资源耗用.总结一句话:什么时候需要数据,什么时候加载. 一.懒加载 1.1 类的懒加载 由javassist产生的代理类与Classes类是继承关系, session.load()方法产生的是代理对象,该代理类是持久化类的子类 /** * 类的懒加载 */ @Test public void testClass_l

【Hibernate学习】 —— 抓取策略(注解方式)

当应用程序需要在关联关系间进行导航的时候,hibernate如何获取关联对象的策略. 抓取策略的方式: FetchType.LAZY:懒加载,加载一个实体时,定义懒加载的属性不会马上从数据库中加载. FetchType.EAGER:急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载. 在项目中的体现,我这里有两个实体,一个放基础数据的实体,另一个是放操作记录的实体.这两个实体的关系是一对一关系,因此要把基础数据中的主键放在操作记录中作为外键,查询的时候查询操作记录表顺便把基础表相关信息

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

一.抓取策略. 1.hibernate中提供了三种抓取策略. (1)连接抓取(Join Fetch):这种抓取方式是默认的抓取方式.使用这种抓取方式hibernate会在select中内连接的方式获取对象的关联对象或者关联集合. (2)查询抓取(select Fetch):这种抓取方式会另外发送一条select语句抓取当前对象的关联实体或者集合.除非指定lazy=false,否则只有在真正访问关联关系的时候才会执行第二条select语句. (3)子查询抓取(subselect Fetch):另外

Hibernate 原汁原味的四种抓取策略(转)

原文出处:http://www.cnblogs.com/rongxh7/archive/2010/05/12/1733088.html     尊重原作者,访问原创地址 最近在研究 Hibernate 的性能优化的时候碰到了"抓取策略", 由于以前没有详细的研究过, 所以到处找资料, 但是无论从一些讲 Hibernate 书籍,还是他人 Blog 中都没有找到详细 介绍 Hibernate 文档中所说的原汁原味的抓取策略, 综合懒加载等等特性混在了一起, 所 以在这自己在借鉴了他人的基

Hibernate fetch 抓取策略

上一篇文章(Hibernate的延迟加载 ,懒加载,lazy)说到Hibernate的延迟加载跟fetch的配置还有一定关系,下面就来讨论下fetch的用法. 抓取策略(fetch)是指当我们去查询一个对象里面所关联的其他对象时,按照哪种方法去抓取关联对象. fetch策略一共有四种:select.subselect.join.batch,下面我们一一介绍.我们还是用上面介绍延迟加载的相关表和实体类. Company表: Employee表(employee_company_id为外键) Com