Hibernate 性能优化策略和缓存详解

 版本:Hibernate3.2

1.1 目的
1.2 范围
1.3 定义、首字母缩写词和缩略语
1.4 参考资料
1.5 概述
2.     缓存策略
2.1 什么是缓存?
即Hibernate将数据临时存放在内存中,以便加快数据的存取速度。为此,我们可以想象,缓存的实现,就类似于一个Map对象,首先需要一个key,以便定位相应被缓存的数据,而它的value值,便是被缓存的数据。
 
2.2 一级缓存
即session级别的缓存,随着session的关闭而消失,load/iterator操作,会从一级缓存中查找数据,如果找不到,再到数据库里面查找。Query.list操作,如果没有配置查询缓存,将直接从数据库中获取数据。
 
2.3 二级缓存
即SessionFactory级别的缓存。默认的情况下是打开的。这是一个全局缓存策略。它可以对对象的数据进行全局缓存。
2.4 查询缓存
即对查询的结果集进行缓存处理,以便下次相同条件相同HQL的情况下可以直接从缓存中获取数据。
 
3.     二级缓存
3.1.1           如何打开二级缓存?
需要更改hibernate配置文件:
1、 打开二级缓存(默认情况下是打开的)
a)       true 
2、 指定缓存策略提供商
a)       org.hibernate.cache.EhCacheProvider 
 
3.1.2           二级缓存是对对象数据的缓存
为了让hibernate对对象进行缓存,你必须指定需要缓存哪些类的对象,这有两种方法可以达到这个目的:
1、 在hibernate配置文件中指定,如
2、 在类的映射文件中(即标签下指定),如
<”read-only”/>
 
如果你打开了对对象的缓存,那么,所有对这个对象的查询操作的结果,都会被缓存起来。Hibernate将使用对象的键值作为缓存的key值,对象的数据作为缓存的value值。
打开了对象缓存,只有在对对象进行查询操作的时候,才会起作用,如createQuery(“from Student”).iterate()
 
3.1.3           缓存策略
缓存有几种形式,可以在映射文件中配置:

 

cache标签的 usage属性 提供缓存对象的事务隔离机制,可选值有以下几种:

 

read-only

 

(只读,适用于很少变更的静态数据/历史数据)。只有该表正在被查询访问,其它用户就不用修改或删除这个表。即时不是同一条数据也不行。相当于锁住了该表。

 

read-write

 

可读可写。读写互不影响且数据同步。比较普遍的形式,效率一般。

 

nonstrict-read-write

 

如果程序对并发数据修改要求不是非常严格,只是偶尔需要更新数据,可以采用本选项,以减少无谓的检查,获得较好的性能。

 

transactional

 

JTA中,且支持的缓存产品较少。事务性cache。cache 的相关操作也被添加到事务之中,如果由于某种原因导致事务失败,我们可以连同缓冲池中的数据一同回滚到事务开始之前的状态。目前Hibernate 内置的Cache 中,只有JBossCache 支持事务性的Cache实现。

 
 
4.     查询缓存
 
查询缓存的作用,是对list操作的查询结果集进行缓存!
 
我们使用list操作的时候,如果启用了查询缓存,hibernate将根据当前查询的HQL语句(及其参数值)计算出一个缓存的key值;查询结果集,将作为缓存的value值(但如果查询结果集是一个对象结果集的话,其缓存的value值是对象的ID集合,而不是对象集合本身)。
 
可以在hibernate配置文件中添加:
true 
以便打开查询缓存。
 
查询缓存,对对象查询,将缓存其ID列表;对普通查询,将缓存整个数据集合。所以,对于对象查询,需要配合二级缓存来使用。
 
在打开了查询缓存之后,需要注意,调用query.list()操作之前,必须显式调用query.setCachable(true)来标识某个查询使用缓存。
 
 
5.     关于load、get、iterate和list操作在缓存中的作用
5.1 Load/get
这个方法,用于加载某个对象。如果打开了二级缓存,加载的对象数据将会被缓存。缓存的key是对象的ID,缓存的value是对象的值。
5.2 Iterate
使用iterate进行查询,分成两种不同的情况:
1、 使用iterate方法进行对象查询,如createQuery(“from Student”).iterate(),这个时候,如果打开了二级缓存,其加载的对象集合,将会被缓存。缓存的key为对象的ID值,缓存的value是对象的数据。
2、 使用iterate方法进行其它查询,如createQuery(“select name,sex from Student”).iterate(),这个时候,不管有没有打开二级缓存(以及查询缓存),其查询的结果集都不会进行缓存。
 
5.3 List
查询缓存只对list操作起作用。
使用List进行查询,也分成两种情况:
1、 使用list方法进行对象查询,如createQuery(“from Student”).list(),这个时候,
a)       如果打开了查询缓存,并使用查询缓存(query.setCachable(true);),hibernate将对对象的ID列表进行缓存
b)       如果同时打开了这个对象的二级缓存,那么hibernate就会将这个对象的数据加入二级缓存中。
2、 使用list方法进行普通查询,如createQuery(“select name,sex from Student”).list(),这个时候,
a)       如果打开了查询缓存,并使用查询缓存(query.setCachable(true);),hibernate将对查询的结果集进行缓存
b)       不管有没有打开二级缓存,二级缓存的任何设置,对这种类型的查询,不会产生任何影响(因为二级缓存只对对象的数据进行缓存,而不是某些查询结果集)
 
 
5.4 Session如何与二级缓存交互?
Session接口通过CacheMode来定制与二级缓存之间的交互方法:
 
 
 
6.     抓取策略
 
抓取策略,即如何获取数据的策略。
 
下面以下述模型为例:
 
班级与学生模型,之间是一对多双向关联:
 
<hibernate-mapping>
    <class name="com.bjsxt.hibernate.one2many.Classes" lazy="false" batch-size="10" table="T_Classes">
       <id name="id">
           <generator class="native"/>
       </id>
       <property name="name"/>
       <set name="students" inverse="true" lazy="false" cascade="all" >
           <key column="classesid"/>
           <one-to-many class="com.bjsxt.hibernate.one2many.Student"/>
       </set>
    </class>
    
    <class name="com.bjsxt.hibernate.one2many.Student" lazy="false" table="T_Student">
       
       <id name="id">
           <generator class="native"/>
       </id>
       <property name="name" length="20"/>
       <property name="sex" length="10" />
       <many-to-one lazy="false" name="classes" column="classesid"/>
    </class>
</hibernate-mapping> 
 
 
 
·         连接抓取(Join fetching) - Hibernate通过 在SELECT语句使用OUTER JOIN(外连接)来 获得对象的关联实例或者关联集合。 连接抓取策略可以被定义在或集合(如)标签上。这种抓取策略,对load/get操作有效。
·         如在Student的标签上设置fetch=”join”,当我们load/get一个Student的时候,其classes属性的值,将通过一个outter join连接查询来获取
·         或在Classes类的标签上设置fetch=”join”,当我们load/get一个Classes类的实例的时候,其集合数据,也是通过一个outter join连接查询来抓取
·         查询抓取(Select fetching) - 另外发送一条 SELECT 语句抓取当前对象的关联实体或集合。除非你显式的指定lazy="false"禁止 延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。 这种抓取策略,设置方法为:fetch=”select”; 
·         如在set标签上设置fetch=”select”,下面的查询:List list = session.createQuery("from Classes cls where id in (1,22)").list();将产生如下结果:
Hibernate: select classes0_.id as id7_, classes0_.name as name7_ from T_Classes classes0_ where classes0_.id in (1 , 22)
 
Hibernate: select students0_.classesid as classesid1_, students0_.id as id1_, students0_.id as id8_0_, students0_.name as name8_0_, students0_.sex as sex8_0_, students0_.classesid as classesid8_0_ from T_Student students0_ where students0_.classesid=?
 
Hibernate: select students0_.classesid as classesid1_, students0_.id as id1_, students0_.id as id8_0_, students0_.name as name8_0_, students0_.sex as sex8_0_, students0_.classesid as classesid8_0_ from T_Student students0_ where students0_.classesid=?
可见,总共发出:第一,查询Classes的数据;第二,因为查询结果集中有两个Classes对象,所以针对每个对象,都发出了一个查询语句以便查询其students集合的数据。
·          
·         子查询抓取(Subselect fetching) - 另外发送一条SELECT 语句抓取在前面查询到(或者抓取到)的所有实体对象的关联集合。除非你显式的指定lazy="false" 禁止延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。 设置方法是:fetch=”subselect”,它只能被设置在集合映射的属性上。
·         如在set标签上设置fetch=”sebselect”,下面的查询:List list = session.createQuery("from Classes cls where id in (1,22)").list();在list对象中,将包含两个Classes对象的实例,假设其集合上配置lazy=”false”,我们立刻就能看到hibernate的subselect抓取策略是:
以下是hibernate生成的SQL语句:
Hibernate: select classes0_.id as id7_, classes0_.name as name7_ from T_Classes classes0_ where classes0_.id in (1 , 22)
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/breeze2003/archive/2007/10/25/1843212.aspx
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值