hibernate的检索策略

本文深入探讨Hibernate中的三种检索策略:立即检索、延迟检索与迫切左外连接检索,以及它们在类级别与关联级别的应用。文章详细解释了每种策略的工作原理、优缺点及其适用场景。

Hibernate检索策略:  

立即检索、延迟检索、迫切左外连接检索  

Hibernate检索策略应用对象级别:类级别、关联级别  

以下表格为类级别和关联级别可选的检索策略及默认的检索策略  
检索策略的作用域  
可选的检索策略  
默认的检索策略  
运行时行为受影响的Session的检索方法  
类级别  
立即加载  
延迟加载  
立即检索  
Load()方法  
关联级别  
立即加载  
延迟加载  
迫切左外连接检索  
多对一或者一对一为迫切左外连接检索  
一对多或者多对多为立即检索  
Get()Load()Find()方法  

对象-关系映射文件中设定检索策略的属性  

属性  
可选值  
默认值  
描述  
lazy  
truefalse  
false  
如果为true表示使用延迟加载,如果为false表示使用立即加载  
outer-join  
autotruefalse  
<many-to-one>元素和  
<one-to-one>元素中为auto,在<one-to-many>元素和<many-to-many>元素中为false  

如果为true表示使用迫切左外连接检索。在<many-to-one><one-to-one>、和<set>元素中包含此属性  
如果为false表示使用立即加载  
batch-size  
正整数  
1  
设定批量检索的数量。如果设定此项合理的取值在310之间  

hibernate还允许在应用程序中以编程方式显示设定检索策略。程序代码中的检索策略会覆盖映射文件中配置的检索策略,如果程序代码没有显示设定检索策略,则采用映射文件中配置的检索策略。

类级别的检索策略:  

类级别可选的检索策略包括立即检索和延迟检索,默认立即检索。如果<class>元素的lazy属性为true,则表示采用延迟检索;如果lazy属性为false,则表示立即检索。lazy属性默认值为false。
在类级别中应该优先考虑使用立即检索策略,因为在大多数情况下,当应用程序通过session的load()方法加载了一个持久化类的对象后,总是立即访问它。
延迟检索:
<class name="mypack.Customer" table="CUSTOMERS" lazy="true">
当执行session的load()方法时,hibernate不会立即执行查询CUSTOMERS表的select语句,仅仅返回Customer类的代理类实例,这个代理类具有以下的特征:
由hibernate在运行时动态产生,它扩展了Customer类,因此它集成了Customer类的所有属性和方法,但它的实现对于应用程序是透明的。
当hibernate创建Customer代理类实例时,仅仅初始化它的OID属性,其他属性都为null,因此这个代理类实例占用的内存很少
当应用程序第一次访问Customer代理类实例时(例如get、set方法,除了getId,因为id已经在代理类中了),hibernate会初始化代理类实例,初始化过程中执行select语句,真正从数据库中加载Customer对象的所有数据。
hibernate是采用CGLIB工具来生成持久化类的代理类。
lazy属性为true时,会影响Session的load()方法的各种运行时行为:
①如果加载Customer对象在数据库中不存在,Session的load()方法不会抛出异常,只有当运行get方法时才会抛出异常
②如果在整个session范围内,应用程序都没有访问过Customer对象,那么Customer代理类的实例一直不会被初始化,Hibernate不会执行任何select语句。
③net.sf.hibernate.Hibernate类的initialize()静态方法用于在session范围内显示初始化代理类实例,isInitialized()方法用于判断代理类实例是否已经被初始化。
值得注意的是,不管Customer.hbm.xml文件的<class>元素的lazy属性是true还是false,session的get()和find()方法在Customer类级别总是使用立即检索策略。
 

关联级别的检索策略  

一对多和多对多关联的检索策略,<set>属性如下

lazy属性  
outer-join属性  
检索策略  
false  
false  
采用立即检索,这是默认的检索策略,当使用Hibernate的第二级缓存时,可以考虑采用立即检索。  
true  
false  
采用延迟检索  
false  
true  
采用迫切左外连接检索,对于Hibernate2.0以下,再映射文件中如果有多个<set>元素,只允许有一个<set>元素的outer-join属性为true  
true  
true  
没有任何意义  


注意:对于Session.find()方法会忽略迫切左外连接检索,采用立即检索策略(如果hql语句中自己撰写了外连接,则会外连接检索)  
多对一和一对一关联的检索策略  
以订单和顾客为例,Order对象与Custom对象之间的多对一关系  
Order.hbml.xml  
<many-to-one>元素的  
outer-join属性  
Custom.hbm.xml<class>元素的lazy属性  
检索order对象时对关联的custom对象使用的检索策略  
auto  
true  
延迟检索  
auto  
false  
迫切左外连接检索  
true  
true  
迫切左外连接检索  
true  
false  
迫切左外连接检索  
false  
true  
延迟检索  
false  
false  
立即检索  

批量检索:  

设置<class>元素的batch-size,这样再进行查询时能够在Sql中采用or连接词减少查询次数。

三种检索模式比较:


检索策略
优点 缺点 适用性

立即检索

对应用程序完全透明,不管对象处于持久化状态,还是游离状态,应用程序都可以方便的从一个对象导航到与它关联的对象

1.select语句太多;
2.可能会加载应用程序不需要访问的对象白白浪费许多内存空间

1.类级别

2.应用程序需要立即访问的对象

3.使用了二级缓存

延迟检索

由应用程序决定需要加载哪些对象,可以避免可执行多余的select语句,以及避免加载应用程序不需要访问的对象。因此能提高检索性能,并且能节省内存空间

应用程序如果希望访问游离状态代理类实例,必须保证他在持久化状态时已经被初始化



1.一对多或者多对多关联

2.应用程序不需要立即访问或者根本不访问的对象


迫切左外连接

1.对应用程序完全透明,不管对象处于持久化状态,还是游离状态,应用程序都可以方便地冲一个对象导航到与它关联的对象。
2.使用了外连接,select语句数目少;

1.可能会加载应用程序不需要访问的对象,白白浪费许多内存空间;
2.复杂的数据库表连接也会影响检索性能;

1.多对一或者一对一关联

2.应用程序需要立即访问的对象

3.数据库系统具有良好的表连接性能



提高查询性能

1、尽量使用迫切连接,以减少查询数据库的次数。

2、对使用延迟加载或者立即检索策略设置批量 查询数目,以检索查询数据库的次数。

3、使用查询缓存

4、有的时候数据量较大,只负责显示的数据可使用Sql查询,以减少缓存空间。

5、尽量减少返回记录集字段的数目,只返回所需要的字段。

6、使用集合过滤,也就是说通过第一次查询的结果来再次进行查询。

HQL方式与QBC方式的不同

1、HQL方式功能强大,可实现分组,外连、内连,而QBC则没有这些功能。

2、HQL语句写法接近Sql语句方式,容易上手。

3、HQL语句无法在编译期检查错误。而QBC能够做到。

4、QBC是面向对象的,而HQL语句还不是面向对象编程。

5、QBC能够动态创建查询,而HQL不能

6、QBC提供了接口,扩展性好,HQL方式不具有扩展性。


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值