”一天一节“之Hibernate的缓存机制

Hibernate的缓存机制 

 

Hibernate的数据缓存根据它的作用范围或生命周期的不同大致分为两种:一级缓存和二级缓存,下面分别说明下两个缓存:

 

 

1. 一级缓存

Hibernate的一级缓存作用范围是在同一个session下,也就是在同一个事务级别下,它随着session的销亡而销亡。Hibernate的一级缓存一般情况下是由hibernate自行维护的,如果我们要手动去维护,hibernate也提供了两个方法:

session.evict(Object obj);//将某个特定的的对象从一级缓存中清除出去

Session.clear(); //清除一级缓存中的所有对象

 

 

Hibernate一级缓存的实现原理,也是非常简单的,这里针对hibernate2来说明下,在Session接口的实现类SessionImpl中定义了许多的Map对象,这些Map维护这与当前session相关联的所以PO状态,当我们查询实体对象时,会首先根据id和加载类与在对应的Map结构中匹配,如果命中则直接讲结果对象返回,否则到数据库中去加载数据,并将加载对象放入这些Map中进行管理。另外这些Map结构都是私有的,所以说明了一级缓存是随着session的销亡而销亡的。

 

 

2. 二级缓存

Hibernate的二级缓存作用范围是一个SessionFactory下的所有session实现共享,其随着SessionFactory的关闭而消亡。

 

虽然说二级缓存可以带来性能上的优化但是还是要因事而论,比如一个聊天系统里提供一个查看用户历史聊天记录,可能要查询近几个月所有的记录,而且基本上这些记录不可能被共享(本用户只查看自己的记录),如果这里使用缓存管理,并且是多用户并行操作,可想而知会给内存带来什么后果!

  

Hibernate本身其实并没有对二级缓存提供很好的实现(只提供了一个基于hashtable的简单实现以供调试),而是为众多第三方实现提供了接口。下面来看个基于EHCache的二级缓存配置实现:

1. 导入ehcache.1.2.3.jar包;

2. 配置ehcache.xml;

 

<?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>

 

3. 在Hibernate配置文件中设置:

<!-- 配置 hibernate 二级缓存 -->
	<property name="hibernate.cache.use_second_level_cache">true
	</property>
<property ame="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider
</property>

 

<!--EndFragment-->

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

 

测试代码:

public static void main(String[] args) {
    long star = System.currentTimeMillis();
		
    Session session = HibernateUtils.getSession();
    Transaction tr = session.beginTransaction();
    Query query = session.createQuery("from User3");
    System.out.println(((User3)query.iterate().next()).getName());
    tr.commit();
    session.close();
		
    Session session1 = HibernateUtils.getSession();
    Transaction tr1 = session1.beginTransaction();
    Query query1 = session1.createQuery("from User3");
    System.out.println(((User3)query1.iterate().nex()).getName());
    tr1.commit();
    session1.close();
		
    System.out.println( System.currentTimeMillis() - star +" ms");
				
}

 

 

<!--EndFragment-->

 

<!--EndFragment-->

相关推荐