通过看孙卫琴的精通Hibernate和平时自己的使用,对他的几种检索策略有了更深的认识,再次总结一下
问题的引出:
Customer和Order的经典一对多场景<o:p></o:p>
Customer表
<o:p>
ID<o:p></o:p>
|
ORDER_NUMBER<o:p></o:p>
|
CUSTOMER_ID<o:p></o:p>
|
1<o:p></o:p>
|
Tom_order001<o:p></o:p>
|
1<o:p></o:p>
|
2<o:p></o:p>
|
Tom_order002<o:p></o:p>
|
1<o:p></o:p>
|
3<o:p></o:p>
|
Mike_order001<o:p></o:p>
|
2<o:p></o:p>
|
4<o:p></o:p>
|
Jack_order001<o:p></o:p>
|
3<o:p></o:p>
|
5<o:p></o:p>
|
TLinda_order001<o:p></o:p>
|
4<o:p></o:p>
|
6<o:p></o:p>
|
Unknown_order001<o:p></o:p>
|
null<o:p></o:p>
|
</o:p>
Oder表<o:p></o:p>
ID<o:p></o:p>
|
NAME<o:p></o:p>
|
1<o:p></o:p>
|
Tom<o:p></o:p>
|
2<o:p></o:p>
|
Mike<o:p></o:p>
|
3<o:p></o:p>
|
Jack<o:p></o:p>
|
4<o:p></o:p>
|
Linda<o:p></o:p>
|
在Session缓存中存放的就相互关联的对象图,从数据库中加载Customer时,会同时加载所有关联的Order对象,这就产生了如下问题:<o:p></o:p>
当执行session的find方法查询所有customer对象时<o:p></o:p>
java 代码
- List customers = session.find(“from Customer as c”);
运行find方法时,Hibernate将先查询CUSTOMERS表中的所有记录,然后根据记录ID到ORDER表里查询相关的记录.Hibernate依次执行一下select语句:<o:p></o:p>
sql 代码
- 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;
通过以上5条select语句,Hibernate最后加载了4个Customer对象和5个Order对象.Hiberante在检索语customer关联的Order对象时使用了默认的立即检索策略,这种方式存在两大缺点<o:p></o:p>
1. select语句太多,频繁访问DB会影响检索性能.如果需要查询n个Customer对象,那么必须执行n+1次select语句,这种检索策略没有利用sql的连接查询功能,<o:p></o:p>
如以上5条语句可以用1句左外连接来完成<o:p></o:p>
<o:p>
sql 代码
- select * from CUSTOMERS left outer join ORDERS on CUSTOMERS.ID=ORDERS.CUSTOMERS_ID
查询出了所有CUSTOMERS表所有记录和匹配的ORDERS表记录<o:p></o:p>
2.如果只需要访问Customer对象,不需要Order对象时,加载Order对象时多余的操作,而且浪费了许多内存空间.<o:p></o:p>
<o:p> Hibernate的三种检索策略,为了解决立即检索的问题,Hibernate提供了其他两种检索策略,即延迟和迫切左外连接检索.</o:p>
<o:p>
一.立即检索<o:p></o:p>
Hibernate的默认检索策略,当执行session 的查询方法时,会把相关联的表的数据全部查询出来.
二延迟检索<o:p></o:p>
包括类级别和集合级别的延迟加载.<o:p></o:p>
1.类级别<o:p></o:p>
某个类采用延迟加载<o:p></o:p>
<class name="”…’" lazy="”true”"></class><o:p></o:p>
只和session的load方法有关,执行load方法时仅返回Customer的代理类实例.<o:p></o:p>
代理类实例有一下特征<o:p></o:p>
1)有Hibernate动态生成,扩展了Customer类,因此它继承了Customer的所有属性和放,但对于应用程序是透明的.<o:p></o:p>
2)词代理类实例仅初始化了OID属性,其他属性为null,因此它占的内存很少<o:p></o:p>
3)第一次访问代理类实例的属性(除了OID属性,它已有值)时, Hiberante会初始化此实例,产生select语句.<o:p></o:p>
注:Hibernate采用CGLIB工具来生成持久化类的代理类CGLIB是一个功能强大的JAVA字节码生成工具,它能在程序运行时动态生成扩展Java类或者实现Java接口的代理类.关于CGLIB的更多信息,可到网站http://cglib.sourceforge.net了解.,<o:p></o:p>
2.集合级别<o:p></o:p>
当不使用相关表的数据时, 在Custom映射文件中set属性设置的 lazy="true",此时不会立即检索相关表,
需注意<o:p></o:p>
1)并没有创建Order代理类实例,也无法创建因为还不知道与Customer关联的所有Order对象的OID.这时Customer的orders属性引用的是Hibernate提供的集合代理类实例.<o:p></o:p>
2)当应用程序第一次要使用相关表的数据时,才从DB的相关表中检索相关数据。<o:p></o:p>
3)只有当集合代理类的实例处于持久化状态时,才可以初始化,以后才可使用,否则会抛出延迟初始化错误:ERROR:LazerInitiater:63........<o:p></o:p>
三.迫切左外连接<o:p></o:p>
默认情况下,多对一关联采用的方法。如果把映射文件的<many-to-one></many-to-one>many-to-one元素outer-join 值设为"true",则总是采用此策略。<o:p></o:p>
Hibernate允许在应用程序的HQL语句中显示指定迫切左外连接检索,它会覆盖配置文件的检索策略。<o:p></o:p>
如
- 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 " )
第一句会采用映射文件中的检索策略,而第二句会覆盖映射文件的策略。
下面是三种检索策略的比较
检索策略
|
优点
|
缺点
|
优先使用场合
|
立即检索
|
1) 对应用程序透明,不管对象在持久化或游历状态.应用程序都可以方便的从一个对象导航到与它关联的对象
2) Sql简单,速度快
|
3) select语句数目太多
4) 可能会加载与不需要访问的对象,浪费内存空间
|
1) 类级别
2) 应用需立即访问的对象
3) 使用了二级缓存
|
延迟检索
|
1) 有程序决定需要加载那些对象,避免多余的select语句
2) 避免加载不需要访问的对象,节省内存空间,提高检索性能
3) Sql简单,速度快
|
应用如果访问游历的代理类实例,必须保证它在持久化状态时已被初始化
|
1) 一对多或多对多
2) 应用不会立即或根本不会访问的对象.
|
迫切左外连接
|
1) 对应用程序透明,不管对象在持久化或游历状态.应用程序都可以方便的从一个对象导航到与它关联的对象
2) 使用了外连接,select语句少,减少访问数据库频率
|
1) 可能会加载不必要的对象,浪费空间
2) 如果表连接过于负责,sql负责度高,,会影响性能
|
1) 多对一或一对一
2) 应用会立即访问的对象
3) 数据库具有良好的表连接性能
|
|
总之,对于实际的应用,为了选择合适的检索策略,需要测试应用程序的各个用例,跟踪使用不用检索策略时Hibernate执行的sql语句,可以百Hibernate的配置文件的showsql属性设为true,输出sql。根据特定的关系模型,比较查询性能。
到底是使用外连接查询快,
sql 代码
- select * from CUSTOMERS left outer join ORDERS on CUSTOMERS.ID=ORDERS.CUSTOMERS_ID where CUSTOMERS.ID=1
还是分开的select语句快
sql 代码
- select * from CUSTOMERS
- select * from ORDERS where CUSTOMER_ID=1
不断的调解检索策略,以便在减少select语句和将少select语句复杂度之间找到平衡点,获得最佳的检索性能。
</o:p></o:p>
分享到:
相关推荐
### Hibernate的检索策略详解 #### 一、概述 在Java持久化框架Hibernate中,检索策略是一种重要的机制,它主要用于控制对象何时以及如何加载到应用程序内存中。合理的检索策略不仅可以提高应用性能,还能简化代码...
一、Hibernate检索方式 1. **HQL(Hibernate Query Language)**: HQL是Hibernate提供的面向对象的查询语言,类似于SQL,但它是基于类和对象的。你可以通过HQL来查询、更新和删除对象,而无需关心底层的SQL语法。...
### Hibernate知识点总结 #### 一、Hibernate概述 ...通过以上内容,我们了解了Hibernate的基本概念、配置步骤、核心类以及查询语言和检索策略等内容,这对于高效地使用Hibernate框架是非常有帮助的。
【Hibernate 简单 PPT 总结】 Hibernate 是一个流行的开源对象关系映射(ORM)框架,它简化了Java应用程序对数据库的操作。通过提供一套API和元数据,Hibernate允许开发者将业务对象直接映射到数据库表,从而避免了...
### Hibernate检索方式详解 #### 一、概述 Hibernate是一个强大的对象关系映射(ORM)框架,它可以将Java对象与数据库表进行映射,使得开发者能够更方便地进行数据的持久化操作。在Hibernate中,提供了多种检索...
**三、Hibernate的检索策略** 1. **类级别的检索策略** - **立即检索**(默认):`lazy="true"`,加载对象时立即执行SQL。 - **延迟检索**(`lazy="false"`):不立即执行SQL,返回代理对象。 2. **关联的检索...
**使用Hibernate Search实现全文检索及文档管理** 在Java开发中,全文检索和文档管理是常见的需求,特别是对于大型的企业级应用。Hibernate Search是Hibernate ORM框架的一个扩展,它提供了对数据库中的对象进行...
总结来说,选择合适的检索策略是优化Hibernate应用性能的关键。立即检索策略适合简单场景,延迟检索策略适用于优化内存和减少数据库交互,而迫切左外连接检索策略则在需要一次性加载所有关联数据时发挥作用。开发者...
学习成长路,Hibernate总结: 1.Hibernate入门优缺点、 2.Hibernate的操作CRUD、 3.主键生成机制、 4.持久化对象的状态、 ...8.Hibernate检索策略(fetch抓取策略)、 9.二级缓存、 10.Hbernate的检索方式(HQL语句)
- **Hibernate中的n+1查询问题**:当使用默认的立即检索策略时,Hibernate会在检索一个对象的同时检索其关联的所有对象。例如,在一个`Customer`与多个`Order`的关联关系中,如果数据库中有`n`个客户,则Hibernate将...
Hibernate支持多种主键策略,如自动生成(GenerationType.AUTO)、固定值(GenerationType.IDENTITY)等。 4. Session:它是Hibernate的主要工作单元,用于在应用程序和数据库之间建立会话。Session提供了一种透明...
### J2EE系统之-hibernate学习总结 #### 对象持久化理论 - **对象持久化定义**:将对象中的数据转换存储至外部持久性存储设备的过程,如数据库、磁盘等。 - **对象持久化的原因**: - 内存易失性:断电后数据丢失...
**Hibernate 二级缓存总结整理** 在Java的持久化框架中,Hibernate是一个广泛使用的ORM(对象关系映射)工具,它极大地简化了数据库操作。在处理大数据量或高并发的场景下,为了提高性能和减少数据库负载,...
3. **检索策略和方式**:Hibernate支持多种检索策略,如立即加载(eager)、延迟加载(lazy)等,以及HQL(Hibernate Query Language)、原生SQL等多种查询方式。 4. **数据库事务、并发、缓存与性能优化**:事务...
总结起来,Hibernate 3.6 作为一款成熟的 ORM 框架,通过对象化的数据库操作方式,极大地提升了 Java 应用的开发效率,同时也提供了丰富的功能和优化选项,帮助开发者更好地应对复杂的数据访问需求。
总结来说,Hibernate 是一个强大的 ORM 工具,它通过简化数据库操作和提供对象化的数据处理,极大地提高了开发效率。理解并熟练掌握 Hibernate 的各项功能,对于任何 Java 开发者来说都是至关重要的。
**Hibernate开发各类项目的技术总结** Hibernate,作为Java领域的一个强大对象关系映射(ORM)框架,极大地简化了数据库操作,让开发者可以专注于业务逻辑而非繁琐的SQL语句。在我一年半的开发经验中,我逐渐积累了...
### 三种检索策略及其应用场景 1. **立即检索**:应用程序加载时即获取所有关联对象。适用于类级别的简单关联。 2. **延迟检索**:仅在需要时才加载关联对象,避免不必要的内存占用和提高检索效率。适用于一对多或...