二级缓存
1 对一级缓存和二级缓存分析:
1.1 一级缓存:一级缓存是一个事务中的缓存,只发生在一个session打开之后关闭之前,一般一级缓存是不需要人工管理操作的,但是当应用程序中有时需要大批量更新信息时候也会出现OutOfMemoryException错误,Hibernate也提供了两种方式管理一级缓存:
方法一:session.evict()
此方法一般在执行删除某记录时候执行:
Session. delete(user);
Session. evict(user);
方法二:session.clear()
此方法用于将一级缓存全部清空。
1.2 二级缓存的原理:Hibernate内部只支持一级缓存,表现在session打开关闭之前如果里面有同样的session.get()语句则不会出现第二次查询,不过这个有局限只能局限在sessin打开之后关闭之前;二级缓存突破了这一限制,在session关闭之后也能打开第二个session并在第二个里执行与第一个session里同样的session.get(),然而不通过二次查询数据库也能查到相应数据。
1.3 Hibernate二级缓存的配置:
(1) 设置Hibernate支持二级缓存功能:
在hibernate.cfg.xml配置文件中添加属性:
<property name=" cache.use_second_level_cache ">true</property>
其实Hibernate默认的cache.use_second_level_cache值也是true,所以此属性用户可以不配置。
(2) 设置二级缓存实现的提供商:
在hibernate.cfg.xml配置文件中添加属性:
<property name=" cache.provider_class "> org.hibernate.cache.OSCacheProvider
</property>
二级缓存的实现类有很多,好比:org.hibernate.cache.OSCacheProvider
(3) 设置需要进行二级缓存的类:
方法一:
在hibernate.cfg.xml中添加配置:
<class-cache usage="read-only" class="cn.itcast.domain.User"/>
注:使用策略usage的选项值有四种:
① read-only:如果你的应用程序只需读取一个持久类的实例,而无需对其修改,那么就可以对其进行只读缓存。这是最简单的,也是实用性最好的方法。甚至在群集中,它也能完美地运行。
② read-write:如果应用程序需要更新数据,那么读/写缓存比较合适。
③ nonstrict-read-write:如果应用程序只偶尔需要更新数据(也就是说,两个事物同时更新同一记录的情况很不常见),也不需要十分严格的事务隔离,那么比较适合使用非严格读/写策略。
④ transaction:事务策略提供了全事务的缓存支持,例如对JBoss TreeCache的支持。这样的缓存只能用于JTAG环境中,你必须指定为其transaction.manager_lookup_class属性。
注意:class必须是完整的包括类包的类名。
方法二:没每一个要进行二级缓存的类的映射文件设置:
<class name="User" table="User">
<cache usage="read-only"/>
<id name="id">
<generator class="native"/>
</id>
<component name="name">
<property name="firstName" column="first_name"/>
<property name="lastName" column="last_name"/>
</component>
<property name="birthday"></property>
</class>
注意:在<id>前定义<cache usage="read-only"/>如果映射文件中有集合类(如Set、Map、List等的)映射实体也要另行指定其cache的缓存同步策略并指定region(不过不包括component和 joined-subclass)
另举例如下:
<set name="employees" cascade="save-update" inverse="true">
<cache usage="read-only" region="Employee"/>
<key column="dept_id"></key>
<one-to-many class="Employee"/>
</set>
2 现在查看如下代码:
User user=null;
Session session=null;
try
{
session=HibernateUtil.getSession();
user=(User) session.get(User.class, id);
System.out.println(user.getClass());
//这里在session未关闭之前查询是利用一级缓存
user=(User) session.get(User.class, id);
System.out.println(user.getName());
}
finally
{
if(session!=null)
session.close();
}
try
{ //之前的session关闭了,这里重新打开了一个新的session,这里查询利用的是二级缓存
session=HibernateUtil.getSession();
user=(User) session.get(User.class, id);
}
finally
{
if(session!=null)
session.close();
}
2.1 检测二级缓存性能:
(1) 在hibernate.cfg.xml配置一个属性:
generate_statistics=true
(2) 测试代码:
public static void main(String[] args)
{
User user=addUser();
getUser(user.getId());
Statistics st=HibernateUtil.getSessionFactory().getStatistics();
System.out.println("put"+st.getSecondLevelCachePutCount());
System.out.println("hit"+st.getSecondLevelCacheHitCount());
System.out.println("miss"+st.getSecondLevelCacheMissCount());
}
注意:以上代码作用是分别获取二级缓存中向map中存数据次数、命中数据次数、没命中数据次数。
3 对二级缓存的人工管理:
对二级缓存一般是不用管理的,都是有提供商和hibernate管理好的,不过也提供了几个控制二级缓存的方法:
(1) HibernateUtil.getSessionFactory().evict(User.class);
把二级缓存中User的所有实例清除掉包括继承它的子类实例;
(2) HibernateUtil.getSessionFactory().evict(User.class, id);
把二级缓存中通过id指定的User实例清除掉。
4 增加对查询HQL查询的二级缓存功能:
Query query=session.createQuery("from User where id>20");
像上面这样的查询语句,hibernate是默认不支持二级缓存的,因为每个查询都是有针对性的查询条件,下次查询的命中率不高,但是也是可以设置打开查询二级缓存的。
打开步骤:
(1). 在hibernate.cfg.xml中配置以下属性:
<property name="cache.use_query_cache">true</property>
注意:此属性Hibernate缺省的是false,所以必须配置为true。
(2). 修改代码:
static User query(int id)
{
Session session=null;
session=HibernateUtil.getSession();
Query query=session.createQuery("from User where id>20");
query.setCacheable(true);
User user=(User)query.uniqueResult();
return user;
}
小结:
1. Session的save()方法不适合native生成方式的主键。
2. update,saveOrUpdate,list,iterator,get,load以及Query,Criteria都会填充二级缓存,但只是在查询缓存时候,Session的iterator.getLoad()会从二级缓存中取数据(iterator可能存在N+1此查询)
3.Query.Criteria查询缓存由于命中率较低,所以Hibernate缺省时关闭的.
4.SessionFactory中提供了evictXXX()方法用来清除缓存中的内容。
5.统计信息打开generate_statics,用sessionFactory.getStatics()获取统计信息。
转自:http://blog.163.com/zhangfei_jiayou/blog/static/56244178200983061742668/