Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1970039
  • 博文数量: 606
  • 博客积分: 9991
  • 博客等级: 中将
  • 技术积分: 5725
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-17 19:07
文章分类

全部博文(606)

文章存档

2011年(10)

2010年(67)

2009年(155)

2008年(386)

分类: Java

2008-07-19 20:25:18

Ehcache简介

 

        hibernatesession提供了一级缓存,每个session,对同一个id进行两次load,不会发送两条sql给数据库,但是session关闭的时候,一级缓存就失效了。

 

        二级缓存是SessionFactory级别的全局缓存,它底下可以使用不同的缓存类库,比如ehcacheoscache等,需要设置hibernate.cache.provider_class,我们这里用ehcache,在2.1中就是 hibernate.cache.provider_class=net.sf.hibernate.cache.EhCacheProvider如果使用查询缓存,加上hibernate.cache.use_query_cache=true

  缓存可以简单的看成一个Map,通过key在缓存里面找value

                

         管理Hibernate的缓存

 

                   Session的缓存是内置的,不能被卸载,也被称为Hibernate的第一季缓存。

 

          SessionFactory有一个内置缓存和一个外置缓存,其中外置缓存是可插拨的缓存插件,也被称为Hibernte的第二级缓存。

 

         缓存的实现不仅需要作为物理介质的硬件,同时还需要用于管理缓存的并发访问和过期等策略的软件。因此,缓存是通过软件和硬件同时实现的。

 

         1. HibernateSession的缓存中存发的数据是数据库中数据的拷贝。在数据库数据表现为关系数据形式,而在Session的缓存中数据表现为相互关联的对象。在读写数据库时,Session会负责这两种形式的数据的映射。Session在某些时间点会按照缓存中的数据来同步更新数据库,这一过程称为清理缓存。

 

          2.SessionFactory的缓存可分为两类:内置缓存和外置缓存。SessionFactory的内置还促和Session的缓存在实现方式上比较相似,前者时指SessionFactory对象的一些集合属性宝航的数据,后者是指Session的一些集合属性。SessionFactory的内置缓存中村发了映射员数据和预定义SQL语句,映射员数据是映射文件中数据的拷贝,而预定义SQL语句是在Hibernate初始化阶段根据映射元数据到出来的。SessionFactory的内置缓存是制度缓存,应用不能修改缓存中映射元数据和预定义的SQL语句,SessionFactory无需进行内置缓存与映射文件的同步。

 

          3.SessionFactory的外置缓存和Session缓存存放的都是数据库数据的拷贝。

 

比较Hibernate的第一级缓存和第二级缓存的区别

 

区别之处

第一级缓存

第二级缓存

存放数据的形式

相互关联的持久化对象

对象的散装数据

缓存范围

事务范围,每个事务拥有单独的第一级缓存

进程或群级范围,缓存被同一个进程或群级范围内的所有事务共享

并发访问策略

由于每个事务都拥有单独的第一级缓存,不会出现并发问题,因此无需提供并发访问策略

由于多个事务会同时访问第二级缓存中相同数据,因此必须提供适当的并发访问策略,来保证特定的事务隔离级别

数据过期策略

没有提供过期策略处于第一级缓存中的对象永远不会过期,除非应用程序显示清空缓存或者清除特定的对象。

必须提供数据过期策略,如基于内存的缓存中的对象最大数目,允许对象处于缓存中的最长时间,以及允许对象处于缓存中的最大空闲时间。通过maxElementsInMemory

进行设置。

物理介质

内存

内存和硬盘

缓存的软件实现

Session的实现中包含了缓存的实现

由第三方提供,Hibernate仅提供一些缓存适配器。

启用缓存的方式

通过Session接口执行保存、更新等操作,Hibernate就会启用第一级缓存,把数据库中的数据以对象的形式拷贝到缓存中。

可通过单个集合的粒度上配置第二级缓存。如果类的实例被经常读但很少修改,就可以考虑第二级缓存。只要为某个类或集合配置了第二级缓存,Hibernate在运行时才会把它的实例加入第二级缓存

用户管理缓存的方式

由于内存的容量有限,必须通过恰当的检索策略和检索方式来限制加载对象的数目。Sessionevit()可以显示清空缓存中特定对象,但不推荐这种方法

可以存放大量的数据,数据过期策略的maxElementsInMemory属性值可以控制内存中的对象数目。管理:选择需要使用第二级缓存的持久化类,设置合适的并发访问策略;选择合适的缓存适配器,设置合适的过期策略。SessionFactoryevit()也可以显示清空缓存中特定对象,但不推荐这种方法。

 

进程范围或群级范围缓存,即第二级缓存,会出现并发问题。对第二级缓存可以设置以下四种类型的并发访问策略,每一种策略对应一种事务隔离级别。

1.事务型:对应Repeatable Read

 2.读写型:对应Read Committed

 3.非严格读写型:

 4.只读型:

 

只有符合下面条件的数据才适合与存放到第二级缓存中

 1.很少被修改的数据

 2.不是很重要的数据,允许出现偶尔的并发问题

 3.不会被并发访问的数据

 4.参考数据

 

管理Hibernate的第一级缓存


 Session
为应用程序提供了两个管理缓存的方法:

 1.evict(Object o):从缓存钟清除参数指定的持久换对象

 2.clear():清空缓存钟所有持久化对象

 

 Sessionevict()方法适用于:

 1.不希望Session继续按照该对象的状态变化来同步更新数据库

 2.在批量更新过删除场合,当更新或删除一个对象后,及时释放该对象占用的内存。

 值得注意的是:批量处理最佳方式是直接通过JDBC API执行相关的SQL语句。

 

管理Hibernate的第二级缓存

 

 Hibernate允许选用以下类型的缓存插件

 1.EHCache:可作为进程范围内的缓存,存放数据的物理介质可以是内存或硬盘,支持Hibernate查询缓存。

 2.OpenSymphony OSCache:进程范围,内存或硬盘,丰富的缓存数据过期策略,查询缓存。

 3.SwarmCache:群集范围,不支持查询缓存。

 4.JBossCache:群级范围,支持事务型并发访问策略,支持查询缓存。

 

  Hibernate+ehcache实例:

1、首先设置EhCache,建立配置文件ehcache.XML,默认的位置在class-path,可以放到你的src目录下:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
 <diskStore path="Java.io.tmpdir"/>
<defaultCache
 maxElementsInMemory="10000" <!-- 缓存最大数目 -->
 eternal="false" <!-- 缓存是否持久 -->
 overflowToDisk="true" <!-- 是否保存到磁盘,当系统当机时-->
 timeToIdleSeconds="300" <!-- 当缓存闲置n秒后销毁 -->
 timeToLiveSeconds="180" <!-- 当缓存存活n秒后销毁-->
 diskPersistent="false"
 diskExpiryThreadIntervalSeconds= "120"/>
</ehcache>

2、在Hibernate配置文件中设置:

<!-- 设置Hibernate的缓存接口类,这个类在Hibernate包中 -->
<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
 <!-- 是否使用查询缓存 -->
 <property name="hibernate.cache.use_query_cache">true</property>
如果使用spring调用Hibernate的sessionFactory的话,这样设置:
<!--HibernateSession工厂管理 -->
 <bean id="sessionFactory"

class="org.springFramework.orm.hibernate3.LocalSessionFactoryBean">
 <property name="dataSource">
<ref bean="datasource" />
 </property>
 <property name="hibernateProperties">
 <props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
<prop key="connection.provider_class">

org.hibernate.connection.C3P0ConnectionProvider

</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.provider_class">

org.hibernate.cache.EhCacheProvider

</prop>
 </props>
 </property>
 <property name="mappingDirectoryLocations">
<list>
 <value>/Web-INF/classes/cn/rmic/manager/hibernate/</value>
</list>
 </property>
</bean>

说明一下:如果不设置“查询缓存”,那么hibernate只会缓存使用load()方法获得的单个持久化对象,如果想缓存使用findall()、list()、Iterator()、createCriteria()、createQuery()等方法获得的数据结果集的话,就需要设置hibernate.cache.use_query_cache true才行。

3、在Hbm文件中添加<cache usage="read-only"/>

4、如果需要“查询缓存”,还需要在使用Query或Criteria()时设置其setCacheable(true);属性

5、实践出真知,给一段测试程序,如果成功的话第二次查询时不会读取数据库

package cn.rmic.hibernatesample;

import java.util.List;

import org.hibernate.CacheMode;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;

import cn.rmic.hibernatesample.hibernate.HibernateSessionFactory;
import cn.rmic.manager.po.Resources;

public class testCacheSelectList ...{

 /** *//**
 * @param args
 */
 public static void main(String[] args) ...{
// TODO Auto-generated method stub

Session s=HibernateSessionFactory.getSession();
Criteria c=s.createCriteria(Resources.class);
c.setCacheable(true);
List l=c.list();
// Query q=s.createQuery("From Resources r")
// .setCacheable(true)
// .setCacheRegion("frontpages") ;
// List l=q.list();
Resources resources=(Resources)l.get(0);
System.out.println("-1-"+resources.getName());
HibernateSessionFactory.closeSession();
try ...{
 Thread.sleep(5000);
} catch (InterruptedException e) ...{
 // TODO Auto-generated catch block
 e.printStackTrace();
}
s=HibernateSessionFactory.getSession();
c=s.createCriteria(Resources.class);
c.setCacheable(true);
l=c.list();
// q=s.createQuery("From Resources r").setCacheable(true)
// .setCacheRegion("frontpages");
// l=q.list();
resources=(Resources)l.get(0);
System.out.println("-2-"+resources.getName());
HibernateSessionFactory.closeSession();
 }
}

阅读(1421) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~