首页 > 代码库 > hibernate之缓存

hibernate之缓存

1.   缓存概念应用数据库访问数据库的代价很高,利用持久化的缓存可以减少与数据库之间的交互,可以从缓存中读取。

    注意:缓存使用不当,会造成性能的损失。要在正确使用缓存的前提下,适当情况使用缓存。

2.  持久化缓存的级别:

(1)事务级别:

    缓存对象只能被当前事务使用,每个事务都有自己的缓存。事务结束,缓存也结束。

    缓存数据以关联对象的形式保存,使用内存作为介质,hibernate的一级缓存即是事务级别。   

(2)应用(进程)级别:

    可被当前应用(进程)的所有事务访问。

    分布式应用不能使用该级缓存,使用内存或硬盘作为储存介质。hibernate的二级缓存可以是此。

(3)分布式级别:

    若应用部署在多台服务器的分布式(集群)环境下,数据可被多台服务器共享。

    要慎重使用该级别的缓存,多台服务器同步缓存可能会消耗大量的带宽。hibernate的二级缓存也可以是此 。

3.  hibernate的一级缓存 

 (1)概念:是内置缓存,不能人为地取消,也称session缓存。事务级别的缓存,若一次事务多次修改对象,提交时只会执行一条语句,更新所有的修改。

(2)实现原理:可以把一级缓存想象为session对象维护的一个map对象,保存session使用过的对象,session读取数据时先依据对象的类型和标识符属性查找,没有在读数据库,同时保存在map中。

(3)管理一级缓存:

     使用session.evict() 方法移除缓存对象,使之变为托管状态。

     使用session.clear()方法清除缓存中的所有对象。

     使用session的contains()判断是否在一级缓存中, flush()同步数据与数据库一致,setReadOnly()设置为只读对象(不执行脏数据检查)

4.  hibernate的二级缓存 

 (1)概念:由SessionFactory对象管理,应用级别缓存,又称为SessionFactory缓存。会被整个应用的session共享。先一级,在二级。

 (2)二级缓存组件:hibernate没有自己的二级缓存组件

组件

Provider类

类型

集群

查询缓存

Hashtable

org.hibernate.cache.HashtableCacheProvider

内存

不支持

支持

EHCache

org.hibernate.cache.EhCacheProvider

内存,硬盘

不支持

支持

OSCache

org.hibernate.cache.OSCacheProvider

内存,硬盘

不支持

支持

SwarmCache

org.hibernate.cache.SwarmCacheProvider

集群

支持

不支持

JBoss Cache

org.hibernate.cache.TreeCacheProvider

集群

支持

支持

 (3)二级缓存策略:

●   只读缓存(read-only)

       如果应用程序需要读取一个持久化类的实例,但并不打算修改它们,可以使用read-only缓存。

        对于从来不会修改的数据,如参考数据,可以使用这种并发访问策略。

●   读/写缓存(read-write)

       如果应用程序需要更新数据,该缓存比较合适。如果需要序列化事务隔离级别,那么就不能使用这种缓存策略。

        若在分布式应用中使用该策略,需要底层的缓存组件支持锁定机制。

●   不严格的读/写缓存(nonstrict-read-write)

       如果程序读取频繁且极少更新数据(也就是说,出现两个事务同时更新同一个条目的现象很不常见),也不需要十分严格的事务隔离,适用该缓存。

        对于极少被修改,并且允许偶尔脏读的数据,可以采用这种并发访问策略。

●   事务缓存(transactional)

       transactional缓存策略提供了对全事务的缓存,仅仅用于JTA环境中。它提供了Repeatable Read事务隔离级别。

(4)管理二级缓存:

        SessionFactory对象的evict(Class arg0)方法:

                可以从二级缓存中清除指定的持久化类的所有缓存对象,并释放其占用的资源。

                如:sessionFactory.evict(Category.class);

        SessionFactory对象的evict(Class arg0,Serializable arg1)方法:

                可以从二级缓存中清除某个持久化类的指定缓存对象。

                如:sessionFactory.evict(Category.class,new Integer(1));

        SessionFactory对象的evictCollection(String arg0)方法:

                可以从二级缓存中清除指定的集合对象的缓存。

                如:sessionFactory.evictCollection("com.hibernate.beans.products");

         SessionFactory对象的evictCollection(String arg0,Serializable arg1)方法:

                可以从二级缓存中清除集合对象中的指定对象。

                如:sessionFactory.evictCollection("com.hibernate.beans.products",new Integer(1));

        SessionFactory对象的evictEntity(String arg0)方法:

                可以从二级缓存中清除指定的持久化类的所有缓存对象。

                如:sessionFacotry.evictEntity("com.hibernate.beans.Category");

         SessionFactory对象的evictEntity(String arg0,Serializable arg1)方法:

               可以从二级缓存中清除某个持久化类的指定对象。

               如:sessionFacotry.evictEntity("com.hibernate.beans.Category",new Integer(1));

5.  查询缓存

        查询缓存使用map对象保存被缓存对象,(key值根据sql、查询参数、分页参数等构造)保证同样查询有同样key值;

        hibernate会记录每个表的最后更新时间,并且查询缓存也有时间,hibernate会比较这两个时间判断缓存有效性。

6. 缓存对get(), load(), list(), iterator() 方法的影响

(1)get():先从一级缓存,后直接从数据库。缓存到一级缓存。

(2)load():先从一级缓存,再从二级缓存,最后从数据库。缓存到一二级缓存。

(3)Query的list():先检查是否配置查询缓存,在直接从数据库中;缓存到一二级,查询缓存中。

(4) Query的iterator():先从数据库查询所有符合条件的标识符属性值(id),再通过load()方法查询对应数据。


注:本文参考《Hibernate开发与实战》 刘伟 张利国 电子工业出版社 一书

本文出自 “java我的最爱” 博客,请务必保留此出处http://lindianli.blog.51cto.com/7129432/1433809