1.清楚Hiberante之中缓存的重要作用,
2.深入理解一级缓存的使用
3.深入理解并配置二级缓存的使用
4.实现缓存的交互操作
5.查询缓存的作用
Hiberante中的持久态实际上就利用了缓存的处理机制.
认识缓存
所谓的缓存实际上指的就是一种查询性能的有效提升手段,可以避免数据重复查询所带来的性能开销,通过此方式来进行数据的快速读取,但是并不意味着缓存一定能够提升性能,相反,如果处理不当,也可能造成致命伤害.
在项目的开发之中有两种比较常见的缓存组件:OSCache,EHCache,其中在Hibernate之中主要使用的是ehcache组件,之所以使用此组件主要是考虑到简洁问题,在缓存之中,至少需要考虑以下几种情况:缓存的个数,缓存的数据如何保存,缓存的数据如何同步.
在Hiberante之中主要支持的是两类缓存:
●Session级缓存(一级缓存,first_level_cache):在使用get()或load()方法的时候,对象实际上一直处于持久态的状态,那么这一点就是一级缓存的配置,但是如果Session关闭了,那么一级缓存的内容就将消失,一级缓存永远存在.
●SessionFactory级缓存(二级缓存,second_level_cachae):指的是跨越Session的缓存存在,可以在多个Session对象之中共享数据,二级缓存是需要进行额外配置的.
并且如果你的Hiberante需要使用缓存,那么必须在创建项目的时候就准备好相应的第三方组件包
一级缓存
一级缓存是Session级的缓存,永远都会存在,也就是说如果用户执行了save()或者get()方法后,那么这个对象在Session关闭前会一直被保留下来.
范例:观察一级缓存
package cn.zwb.test;
import java.util.Date;
import cn.zwb.dbc.HibernateSessionFactory;
import cn.zwb.pojo.Member;
public class TestSessionCacheDemoA {
public static void main(String[] args) {
Member vo=new Member();
vo.setMid("6666666");
vo.setName("你好");
vo.setAge(166);
vo.setBirthday(new Date());
vo.setNote("66666");
vo.setSalary(15.0);
HibernateSessionFactory.getSession().save(vo);//瞬时态变为持久态
HibernateSessionFactory.getSession().beginTransaction().commit();
//在保存完成之后,并没有关闭Session的前提下发出了一个查询操作
Member temp=(Member)HibernateSessionFactory.getSession().get(Member.class, "6666666");
System.out.println(temp);
}
}
保存完成之后随后进行查询,但是发现Hibernate并没有发出另外一条SELECT语句,因为此时的对象一旦被保存了,就将在缓存中存在,如果缓存中存在的内容进行查询的时候将不再重复发出查询指令.
一级缓存的操作都在Session接口里面定义了,定义有如下的几个操作方法:
清空所有缓存数据:public void clear();
强制刷新缓冲区:public void flush()throws HiberanteException
清楚一个缓存对象:public void evict(Object object)
如果以后遇见了数据的批量处理,那么一定要注意要按照数据的分批保存一级分批清空的原则来进行处理
面试题:请问如果使用Hibernate进行数据批处理的话,需要注意哪些问题?
Hibernate之中一级的Session缓存会永远存在,也就是说如果使用了save()方法,那么对象信息将一直保存到Session关闭,所以如果存放的内容太多,则有可能造成程序出现问题;
可以使用Session接口中的flush()与clear()两个方法进行强制性的缓存清空,保存缓存的容量不会占用过多.
二级缓存
在Hiberante的默认状态下,每一个Session缓存的数据是不能够进行共享的,
定义一个缓存的配置文件--ehcache.xml文件
<ehcache>
<!-- 此处进行默认的缓存配置 -->
<defaultCache
maxElementsInMemory="10000" 可以缓存的最大的POJO类对象个数
eternal="false" 是否允许该缓存自动失效
timeToIdleSeconds="120" 最小的失效时间
timeToLiveSeconds="120" 最大的保存时间
overflowToDisk="true" 如果保存过多则自动利用磁盘存储缓存数据
/>
</ehcache>
虽然项目里面已经存在有缓存的支持包以及缓存的配置文件,但是如果要想让缓存可以使用还需要在hibernate.cfg.xml文件里面配置使用的缓存类型
<property name="hibernate.cache.region.factory_class">
org.hibernate.cache.ehcache.EhCacheRegionFactory
</property>
此时已经可以使用二级缓存进行开发操作.但是与一级缓存相比,二级缓存的使用更加麻烦,因为在实际的开发之中,并不一定所有的POJO类都可能使用到二级缓存.所以来讲还应该在支持缓存的位置上进行启用,有以下三种的操作形式:
如果你的项目基于*.hbm.xml文件配置的,则可以在Member.xml文件中增加以下配置;
<cache usage="read-only"/>
如果现在使用的是Annotatio,则可以利用以下注解在Member类中配置
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
但是考虑到你的项目可能经常会需要修改,如果都去找每一个文件配置会比较麻烦,那么也可以直接hibernate.cfg.xml文件进行综合的配置
<class-cache usage="read-only" class="cn.zwb.pojo.Member"/>
实际上对于缓存的操作一共有以下几种形式:
READ_ONLY(只读,唯一推荐使用的)只读缓存,在数据查询的时候使用,将查询结果保存在缓存之中以供其他的Session使用
READ_WRITE(读,写缓存):当数据库里面发生变化之后,那么可以进行及时的数据追踪,但是这种操作性能是最差的;
NONSTRICT_READ_WRITE(不严格的读写操作),在数据发生变化之后不会立即进行缓存的更新,而是等待一段时间之后再进行数据的更新操作;
TRANSACTIONAL(事务的处理缓存):如果数据库的中的数据发生了回滚操作后,内存中的数据也要一起发生回滚操作;
缓存交互
如果项目中配置了二级缓存之后,对于程序而言,就相当于只要是通过Session查询的数据都会被默认的保存在二级缓存之中,以供其他的Session使用,但是这些都是默认的配置形式,而用户也可以根据自己的需要来配置是否需要进行二级缓存,而配置的方法主要是在Session接口中:
void setCacheMode(CacheMode cacheMode)