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

全部博文(606)

文章存档

2011年(10)

2010年(67)

2009年(155)

2008年(386)

分类:

2009-03-05 11:28:12

一:hibernate一级缓存

一级缓存很短和session的生命周期一致,一级缓存也叫session级的缓存或事务级缓存

一级缓存是缓存实体对象的,不会缓存普通属性

那些方法支持一级缓存:
 * get()
 * load()
 * iterate(查询实体对象)
 
如何管理一级缓存:
 * session.clear(),session.evict()
 
如何避免一次性大量的实体数据入库导致内存溢出
 * 先flush,再clear
 
向数据库中批量加入1000条数据
for (int i=0; i<1000; i++) {
 Student student = new Student();
 student.setName("s_" + i);
 session.save(student);
 //每20条数据就强制session将数据持久化
 //同时清除缓存,避免大量数据造成内存溢出
 if ( i % 20 == 0) {
  session.flush();
  session.clear();
 }
}
 
如果数据量特别大,考虑采用jdbc实现,如果jdbc也不能满足要求可以考虑采用数据本身的特定导入工具     

二:hibernate二级缓存

    二级缓存是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

    二级缓存也称进程级的缓存或SessionFactory级的缓存,二级缓存可以被所有的session共享,二级缓存的生命周期和SessionFactory的生命周期一致。hibernate为实现二级缓存,只提供二级缓存的接口供第三方来实现(具体可以查看)。二级缓存也是缓存实体对象 ,其实现原理与一级缓存的差不多吧,其方法与一级的相同,只是缓存的生命周期不一样而已:
    * get()
    * load()
    * iterate(查询实体对象)
其中 Query 和Criteria的list() 只会缓存,但不会使用缓存(除非结合查询缓存)。
二级缓存的配置和使用:
    * 将echcache.xml文件拷贝到src下
    * 开启二级缓存,修改hibernate.cfg.xml文件
    true
    * 指定缓存产品提供商,修改hibernate.cfg.xml文件
    org.hibernate.cache.EhCacheProvider
    * 指定那些实体类使用二级缓存(两种方法)
    * 在映射文件中采用标签
    * 在hibernate.cfg.xml文件中,采用标签其缓存策略有read-only,read-write,nonstrict-read-write,transactional,(详细查看 这里有详细介绍;)这里的缓存策略是针对你缓存里面的对象而言的,就比如read-only,它是限制缓存中的对象不能被修改的。   

三、查询缓存
    查询缓存是针对普通属性结果集的缓存,对实体对象的结果集只缓存id(其ID不是对象的真正ID,它与查询的条件相关即where后的条件相关,不同的查询条件,其缓存的id也不一样) ,查询缓存的生命周期,当前关联的表发生修改或是查询条件改变时,那么查询缓存生命周期结束,它不受一级缓存 和二级缓存 的生命周期的影响,要想使用查询缓存需要手动配置如下:
    * 在hibernate.cfg.xml文件中启用查询缓存,如:
    true
    * 在程序中必须手动启用查询缓存,如:
    query.setCacheable(true);

其中 Query 和Criteria的list() 就可利用到查询缓存了。
  

管理Hibernate的缓存

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

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

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

   1. Hibernate的Session的缓存中存发的数据是数据库中数据的拷贝。在数据库数据表现为关系数据形式,而在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():清空缓存钟所有持久化对象
 
Session的evict()方法适用于:
1.不希望Session继续按照该对象的状态变化来同步更新数据库
2.在批量更新过删除场合,当更新或删除一个对象后,及时释放该对象占用的内存。
值得注意的是:批量处理最佳方式是直接通过JDBC API执行相关的SQL语句。
 
管理Hibernate的第二级缓存
 
Hibernate允许选用以下类型的缓存插件
1.EHCache:可作为进程范围内的缓存,存放数据的物理介质可以是内存或硬盘,支持Hibernate查询缓存。
2.OpenSymphony OSCache:进程范围,内存或硬盘,丰富的缓存数据过期策略,查询缓存。
3.SwarmCache:群集范围,不支持查询缓存。
4.JBossCache:群级范围,支持事务型并发访问策略,支持查询缓存。
 
总结:
不要想当然的以为缓存一定能提高性能,仅仅在你能够驾驭它并且条件合适的情况下才是这样的。hibernate的二级缓存限制还是比较多的,不方便用jdbc可能会大大的降低更新性能。在不了解原理的情况下乱用,可能会有1+N的问题。不当的使用还可能导致读出脏数据。 如果受不了hibernate的诸多限制,那么还是自己在应用程序的层面上做缓存吧。
在越高的层面上做缓存,效果就会越好。就好像尽管磁盘有缓存,数据库还是要实现自己的缓存,尽管数据库有缓存,咱们的应用程序还是要做缓存。因为底层的缓存它并不知道高层要用这些数据干什么,只能做的比较通用,而高层可以有针对性的实现缓存,所以在更高的级别上做缓存,效果也要好些吧。
 
       
       
阅读(1049) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~