`

hibernate检索策略(类级别检索,关联基本检索,延迟加载...)(二)

阅读更多

转:http://blog.csdn.net/qking93415981/archive/2007/08/31/1767270.aspx

 

1、hibernate检索策略简介

 Hibernate执行检索方法时(load、get、find),需要获得以下信息:
a. 类级别检索策略:session.load,session.get,session.find方法,直接指定检索的是Customer对象,对Customer对象到底采用立即检索,还是延迟检索?
b. 关联级别检索策略:对与Customer关联的Order对象,即Customer的orders集合,到底采用立即检索 还是延迟检索 迫切左外联接检索
,还是

Hibernate还允许在应用程序中以编程方式显式设定检索策略,同时会覆盖映射文件中配置的检索策略,如果代码没有设定,使用映射文件中配置的检索策略。但是HQL检索方式会忽略映射文件的迫切左外连接检索策略

2、类级别检索策略

类级别可选策略包括立即检索和延迟检索,默认为立即检索。如果<class>元素的lazy属性为true,表示延迟检索;如果lazy属性为false,表示才用立即检索。lazy属性还能决定多对一、一对一关联界别的检索策略。

2.1 立即检索

会立即进行sql查询

2.2 延迟检索

设置<class>中的lazy="true",当session.load()方法执行时,不会立即执行select语句,仅仅返回Customer类的代理类的实例,这个代理类具有以下特征:
a. 由hibernate在运行时动态生成,它扩展了Customer类,但是它的实现对于应用程序是透明的
b. 当hibernate创建Customer代理类的时候,仅仅初始化了他的OID属性,其他属性都是null,因此,占用的内存很少。
c. 当应用程序第一次访问Customer代理类实例时(如调用get或set方法等),hibernate会初始化代理类实例,在初始化过程中执行select语句,真正从数据库中加载Customer对象的所有数据,getID()方法例外。

lazy=true时,会影响load方法的运行时行为:
a. 如果对应的Customer在数据库中不存在,load方法不会抛出异常,只有在getName方法时才会抛出异常。
b. 如果在session范围内,没有访问过Customer对象,那么其代理类的实例不会被初始化,不会执行任何select语句。
c. Hibernate类的initialize静态方法用于在Session范围内显示初始化代理类实例,isInitialized()方法判断代理类实例是否已经被初始化。
d. 程序调用getId()方法时,不会触发Hibernate初始化代理类实例的行为。

注:<class>的lazy="true"不会影响get和find方法, 他们还是使用立即检索策略。

3、一对多,多对多关联的检索策略

在映射文件中,<set>元素用来配置一对多,多对多关联关系。其中有lazy和outer-join属性。

<set>元素不仅用于映射一对多,多对多关联关系,还能映射存放值类型数据的集合(待讲)。
Hibernate为Set集合类也提供了代理类,它扩展了Set接口,与持久化类的代理类不同的是,不管有没有设置延迟检索策略,Session的检索方法在为Customer对象的orders属性赋值时,orders属性总是引用集合代理类的实例。

3.1 立即检索

一对多关联关系的默认检索策略。
包括对Customers表和关联表Orders的检索。在一对多关联级别中不能随意使用立即检索策略。

3.2 延迟检索

设置<set>的属性lazy="true"
仅立即检索Customer对象,同时也不会创建Order代理类的实例,因为无 法知道与Customer关联的所有Order对象的OID。getOrders()方法返回的是Hibernate提供的集合代理类实例,当应用程序第 一次访问它,如调用orders.getIterator()方法时,Hibernate会初始化这个集合代理类实例,并检索所有关联的Order对象。

3.3 批量延迟检索和批量立即检索

<set>元素有一个batch-size属性,用于为延迟检索或立即检索策略设定批量检索的数量。批量检索能减少select语句的数目,提高延迟检索或立即检索的性能。

3.3.1 批量延迟检索

注:批量指的是set中的元素

List customerLists  =  session.find( " from Customer as c " );
Iterator customerIterator 
=  customerLists.iterator();

Customer customer1 
=  (Customer)customerIterator.next();
Customer customer2
=  (Customer)customerIterator.next();
Customer customer3
=  (Customer)customerIterator.next();
Customer customer4
=  (Customer)customerIterator.next();

Iterator orderIterator1 
=  customer1.getOrders().iterator(); // 执行一个select OID=1,初始化orders集合代理类实例
// select * from ORDERS where CUSTOMER_ID=1
Iterator orderIterator2 =  customer2.etOrders().iterator(); // 执行一个select OID=2,初始化orders集合代理类实例
// select * from ORDERS where CUSTOMER_ID=2
Iterator orderIterator3 =  customer3.etOrders().iterator(); // 执行一个select OID=3,初始化orders集合代理类实例
// select * from ORDERS where CUSTOMER_ID=3
Iterator orderIterator4 =  customer4.etOrders().iterator(); // 执行一个select OID=4,初始化orders集合代理类实例
// select * from ORDERS where CUSTOMER_ID=4

可见,为了初始化4个Orders集合代理类实例,必须执行四条查询Orders表的select 语句。为了减少select语句的数目,可以采用批量延迟策略 ,设置<set>元素的 batch-size属性。
<set name="orders inverse="true" lazy="true" batch-size=3>
当 访问customer1.getOrders().iterator()方法时,此时Session的缓存中共有四个orders集合代理类实例没有被初 始化,由于<set>元素的batch-size=3,因此会批量初始化三个orders集合代理类实例:
select * from ORDERS where CUSTOER_ID=1 or CUSTOER_ID=2 or CUSTOER_ID=3

3.3.2 批量立即检索
<set nam="orders" invers="true" batch-size="3">

3.4 迫切左外连接检索

<set name="orders" inverse="true" outer-join="true">
注:也是针对<set>

对于 customer = (Customer)session.get(Customer.class,new Long(1));会执行一下SQL:
select * from CUSTOMERS left outer join ORDERS on CUSTOMERS.ID=ORDERS.CUSTOMER_ID where CUSTOMERS.ID=1;
但是find方法会忽略映射文件中配置的策略。就算配置文件中设置了outer-join="true",但是使用find方法时,仍然会采用立即检索策略:
select * from CUSTOMERS;
select * from ORDERS where CUSTOMER_ID=1;
select * from ORDERS where CUSTOMER_ID=2;
select * from ORDERS where CUSTOMER_ID=3;
select * from ORDERS where CUSTOMER_ID=4;

4、多对一和一对一关联的检索策略

<many-to-one
              name="customer"
              column="CUSTOMER_ID"
              class="mypack.Customer"
/>
<many-to-one>元素有一个outer-join属性,它有三个可选值。
a. auto: 这是默认值。如果<class>元素的lazy属性为true,那么对与Order关联的Customer对象 采用延迟检索策略,否则采用迫切左外连接检索策略。
b. true:不管<class>元素的lazy属性为true还是false,对与Order关联的Customer对象 都采用迫切左外连接检索策略。
c. false:始终不会对与Order关联的Customer对象 采用迫切左外连接检索策略。

对于多对一或一对一关联,应该优先考虑外连接检索策略。因为它使用的select语句数目少。

4.1 迫切左外连接检索

默认情况下,<many-to-one>元素的outer-join属性为auto,<class>元素的lazy属性为false,因此在检索Order对象时, 对关联的Customer对象 使用迫切左外连接检索策略。

对于以下代码:
order = (Order)session.get(Order.class,New Long(1));
在运行session.get()方法时,Hibernate需要决定以下检索策略:
a. 类级别的Order对象的检索策略,get()方法在类级别总是使用立即检索策略。
b. 与Order多对一关联的Customer对象的检索策略:Order.hbm.xml中<many-to-one>元素配置,设outer-join="true",使用迫切左外连接检索策略。
c. 与Customer一对多关联的Order对象的检索策略:Customer.hbm.xml中<set>元素的lazy和outer-join属性配置,设lazy和outer-join属性都为false,使用立即检索策略。

按照以上策略,会执行一下SQL:
select * from ORDERS left outer join CUSTOMERS  on ORDERS.CUSTOMER_ID=CUSTOMER.ID where ORDERS.ID=1

select * from ORDERS  where CUSTOMER_ID=1

通过以上两条select 语句,实际上加载了三个持久化对象:

如果Customer.hbm.xml中的<set>元素的outer-join属性为true,因此对与Customer的order对象也采用迫切外连接检索策略,那么SQL会是这样:
select * from ORDERS o1
left outer join CUSTOMERS c1 on o1.CUSTOMER_ID = c1.ID
left outer join  ORDERS o2 on c1.ID=o2.CUSTOMER_ID
where o1.ID=1
如 果外连接表的数目太多,会影响检索性能,此时可以通过Hibernate配置文件中的hibernate.max_fetch_depth属性来控制外连 接的深度,如果设置hibernate.max_fetch_depth=1则只允许外连接一张表,所以SQL还是两个:
select * from ORDERS left outer join CUSTOMERS  on ORDERS.CUSTOMER_ID=CUSTOMER.ID where ORDERS.ID=1

select * from ORDERS  where CUSTOMER_ID=1

注:对于find方法,会忽略映射文件中配置的迫切左外连接检索策略。

4.2 延迟检索

 如果希望检索Order对象的时候延迟检索关联的Customer对象,需要把Customer.hbm.xml文件 的<class>元素的lazy属性设置为true,Order.hbm.xml文件中的<many-to-one>元素的 outer-join属性可以设置为auto或false.

order = (Order)session.get(Order.class,new Long(1));
//执行:select * from ORDERS where ID=1
Customer customer = order.getCustomer();
//返回一个代理实例
customer.getName();
//执行:select * from CUSTOMERS where ID=1;
//            select * from ORDERS where CUSTOMER_ID=1;(设Customer.hbm.xml中<set>的lazy和outer-join属性都为false,故采用立即检索策略。)

对于一对一关联,如果使用延迟加载策略,必须把<one-to-one>元素的constrained属性设为true:
<one-to-one name="customer" class="mypack.Customer" constrained="true"/>
constrained属性与<many-to-one>元素的not-null属性语义上有些相似,表明Order对象必须和一个Customer对象关联。

4.3 立即检索

Order.hbm.xml中
<many-to-one
              name = "customer"
              column="CUSTOMER_ID"
              class="mypack.Customer"
              outer-join="false"
/>
如果Customer.hbm.xml文件的<class>元素的lazy=false,会对Order关联的Customer对象采用立即检索策略。
对于:Order order = (Order)session.get(Order.class,new Long(1));
会执行以下SQL:
select * from ORDERS where ID=1;
select * from CUSTOMERS  where ID=1;
select * from ORDERS where CUSTOMER_ID=1;//假定关联的Order立即检索

4.4 批量延迟检索和批量立即检索

4.4.1 批量延迟检索

对于以下代码:

List orderLists  =  session.find( " from Order as c " );
// select * from orders
Iterator orderIterator  =  orderLists.iterator();
Order order1 
=  (Order)orderIterator.next();
Order order2 
=  (Order)orderIterator.next();
Order order3 
=  (Order)orderIterator.next();
Order order4 
=  (Order)orderIterator.next();
Order order5 
=  (Order)orderIterator.next();
Order order6 
=  (Order)orderIterator.next();

Customer customer1 
=  order1.getCustomer();
if (customer1  != null ) customer1.getName(); // customer.id=1
// select * from CUSTOMERS where ID=1
// select * from ORDERS where CUSTOMER_ID =1

Customer customer2 
=  order2.getCustomer();
if (customer2  != null ) customer2.getName(); // customer.id=2
// 与order1 关联同一个customer

Customer customer3 
=  order3.getCustomer();
if (customer3  != null ) customer3.getName(); // customer.id=3
// select * from CUSTOMERS where ID=2
// select * from ORDERS where CUSTOMER_ID =2

Customer customer4 
=  order4.getCustomer();
if (customer4  != null ) customer4.getName(); // customer.id=4
// select * from CUSTOMERS where ID=3
// select * from ORDERS where CUSTOMER_ID =3

Customer customer5 
=  order5.getCustomer();
if (customer5  != null ) customer5.getName(); // customer.id=5
// select * from CUSTOMERS where ID=4
// select * from ORDERS where CUSTOMER_ID =4

Customer customer6 
=  order6.getCustomer();
if (customer6  != null ) customer6.getName(); // customer.id=6
// 不存在

实际执行过程:
可见,四个Customer对象必须执行四条Sql语句,如果为了减少Select语句的数目,可以设置:
<class name="mypack,Customer" table="CUSTOMERS" lazy="true" batch-size="3" >
注:设置的是Customer.hbm.xml

会批量初始化三个Customer代理类实例
select * from CUSTOMERS where ID=1 or ID=2 or ID=3;
select * from ORDERS where CUSTOMER_ID=1;
select * from ORDERS where CUSTOMER_ID=2;
select * from ORDERS where CUSTOMER_ID=3;
注:batch-size=3~10;

4.4.2 批量立即检索

设:
Customer.hbm.xml
<class name="mypack,Customer" table="CUSTOMERS" lazy="true" batch-size="4" >
<set name="orders" inverse="true" batch-size="4">

Order.hbm.xml
<many-to-one name="customer" column="CUSTOMER_ID" class="mypack.Customer" outer-join="false'/>
当执行:
session.find("from Order as c");
Order对象采取立即检索,与Order关联的Customer对象采取批量立即检索,对于Customer关联的Order对象也采用批量立即检索:
select  * from ORDERS;
select * from CUSTOMERS where ID=1 or ID=2 or ID=3 or ID=4;
select * from ORDERS where CUSTOMER_ID=1 or  CUSTOMER_ID=2 or CUSTOMER_ID=3 or CUSTOMER_ID=4

5、Hibernate对迫切左外连接检索的限制

Select语句如果包含多个一对多关联的外连接,会导致一次检索出大批量数据,从而影响检索性能,所以对迫切左外连接检索作了以下限制
a. 在一个select 语句中只允许包含一个一对多 关联或多对多 关联的迫切左外连接。
b. 在一个select语句中允许包含多个一对一关联或多对一 关联的迫切左外连接
c. 如果一个类有多个<set>元素,只允许由一个<set>元素的out=join=true.
d.不限制一条select语句中多对一或者一对一迫切左外连接的数目。

 6、在应用程序中显式制定迫切左外连接检索策略

映射文件中设定的检索策略是固定的三种:延迟检索、立即检索、外连接检索。
Hibernate允许在应用程序中覆盖映射文件中设定的检索策略,在运行时决定检索的深度
session.find("from Customer as c where c.id=1");
session.find("from Customer as c left join fetch c.orders where c.id=1");
第二句会覆盖映射文件的配置策略,而使用左外连接检索!

7、总结

 

 

 

 

 

分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    HIBERNATE检索策略

    标题:“HIBERNATE检索策略” 描述:本文深入解析了HIBERNATE的检索策略,为读者提供了一条清晰的学习路径,重点分析了HIBERNATE中的抓取策略及其应用场景,帮助开发者更有效地管理和优化数据加载过程。 在...

    Hibernate的检索策略

    Hibernate支持两种主要的检索策略:类级别检索策略和关联级别检索策略。 #### 二、类级别检索策略 类级别检索策略是指当查询一个实体类时,如何加载该实体类中的属性和关联关系。这通常涉及到单个实体的加载方式,...

    hibernate5--4.检索方式及策略

    一、Hibernate检索方式 1. **HQL(Hibernate Query Language)**: HQL是Hibernate提供的面向对象的查询语言,类似于SQL,但它是基于类和对象的。你可以通过HQL来查询、更新和删除对象,而无需关心底层的SQL语法。...

    hibernate延迟加载解决

    延迟加载是一种优化策略,它使得关联的对象在真正需要时才从数据库中加载,而不是在加载主对象时立即加载所有关联对象。这样可以避免不必要的数据检索,提高应用程序的运行效率。 **2. Hibernate中的延迟加载** 在...

    08.拓薪教育-hibernate4.3的hibernate.cfg.xml基本配置.part2

    hibernate介绍,hibernate.cfg.xml配置,hbm.xml映射文件详解,主键生成策略使用,PO对象状态及状态的转换分析、一级缓存,Hibernate数据检索技术,Hibernate高级映射技术,Hibernate多表联合查询, Hibernate二级...

    hibernate的延迟检索在轻量级J2EE框架中的应用

    - **缓存策略**:结合Hibernate的一级缓存和二级缓存,可以进一步提升延迟加载的效果。通过适当的缓存策略,可以避免频繁的数据库查询,从而提高系统的整体性能。 - **错误处理**:需要注意的是,延迟加载可能会导致...

    08.拓薪教育-hibernate4.3的hibernate.cfg.xml基本配置.part1

    hibernate介绍,hibernate.cfg.xml配置,hbm.xml映射文件详解,主键生成策略使用,PO对象状态及状态的转换分析、一级缓存,Hibernate数据检索技术,Hibernate高级映射技术,Hibernate多表联合查询, Hibernate二级...

    java-Hibernate 检索

    Hibernate 是一个流行的 Java 持久层框架,它提供了多种检索数据的方式,包括导航对象图检索、OID 检索、HQL 检索、QBC 检索和本地 SQL 检索等。下面将详细介绍每种检索方式。 一、导航对象图检索 导航对象图检索...

    Manning.Java.Persistence.with.Hibernate.Nov.2006.pdf

    6. **性能优化**:书中还涵盖了Hibernate的性能优化技巧,如第二级缓存的配置,批处理更新,延迟加载和懒加载策略,以及如何避免N+1查询问题。 7. **实战案例**:书中通常会包含丰富的实例,让读者在实践中掌握...

    hibernate-jar

    10. **Lazy Loading**:一种优化策略,允许延迟加载关联的对象,直到真正需要它们的时候才从数据库中获取。 使用这些核心JAR包,开发者可以轻松地实现Java应用程序的数据持久化,同时避免直接编写SQL语句,提高了...

    Hibernate数据检索(HQL)笔记

    ### Hibernate数据检索(HQL)知识点详解 #### 一、简介 Hibernate 是一款开源的对象关系映射(ORM)框架,它允许开发人员将 Java 对象映射到数据库表中的记录,从而极大地简化了数据访问层的开发工作。本文档基于...

    day36-hibernate检索和优化 02-Hibernate检索方式:简单查询及别名查询

    本教程将深入探讨"day36-hibernate检索和优化 02-Hibernate检索方式:简单查询及别名查询"的主题,通过源码分析和实际工具的应用,来提升数据库查询的效率。 首先,我们了解Hibernate的检索方式。在Hibernate中,...

    Java.Persistence.with.Hibernate.2nd.Edition.2015.10

    6. **高级特性**:Hibernate还支持延迟加载、级联操作、集合映射、继承映射等高级功能。这些特性使得Hibernate能够处理更复杂的企业级应用场景。 7. **性能优化**:最后,书中会涉及如何调优Hibernate应用,包括...

    hibernate的检索

    【Hibernate检索策略】 Hibernate提供三种主要的检索策略:立即检索、延迟检索和迫切左外连接检索。 1. **立即检索**:这种策略将立即加载关联的对象,无论对象是持久化状态还是游离状态。优点是应用程序可以方便...

    J2EE Hibernate-6.ppt

    《J2EE Hibernate-6.ppt》探讨了Hibernate在J2EE环境中的检索策略,主要涉及立即检索策略、延迟检索策略以及迫切左外连接检索策略。 1. **立即检索策略**: 立即检索策略是Hibernate默认的检索方式。在处理一对多...

    hibernate-release-5.3.2.Final

    使用Hibernate ORM通常需要配置Hibernate配置文件(hibernate.cfg.xml),定义数据库连接参数、缓存策略等。实体类需使用注解标注属性与数据库字段的对应关系,然后通过SessionFactory创建Session,进而进行数据操作...

    hibernate源码release-4.1.4.Final版

    Hibernate的懒加载机制可以在需要时才加载关联的对象,避免了大量数据一次性加载导致的内存压力。但需注意防止“懒加载地狱”。 九、性能优化 包括但不限于:合理使用缓存,避免N+1查询问题,使用批处理更新,选择...

    Manning.Java.Persistence.with.Hibernate[Hibernate实战第二版].pdf

    该书详细介绍了Hibernate的基础概念、配置、实体管理、查询语言(HQL和Criteria API)、关联映射、缓存策略、性能优化以及高级特性。通过实际案例,读者可以了解到如何在项目中有效地使用Hibernate进行数据持久化。书...

Global site tag (gtag.js) - Google Analytics