您的位置:首页 > 其它

Hibernate缓存机制

2016-07-03 20:27 246 查看
    缓存的机制在减轻数据库压力方面、提高系统性能方面有很大的作用,在一些数据库框架中也不例外,Hibernate也有它自己的缓存机制。在Hibernate中,缓存分为两级,分别是一级缓存和二级缓存,一级缓存指的是Session级别的缓存,二级缓存指的是SessionFactory级别的缓存。

一级缓存

    一级缓存是Session级别的缓存,是存在于Session中的缓存,也称为事务级缓存。它存在的时间比较短,会随着事务的提交,Session的消失而消失。一级缓存是保存在内存中的,跟其持久化对象相关联。一级缓存是调用Session接口是启动的,它是不会过期的,除非清理缓存或者清理相应的持久化对象。一级缓存有几个方法来管理:

    evit(Object obj):是将指定的对象从一级缓存中清除掉,释放对象占用的资源。

    clear():清除一级缓存中所有的对象,释放他们占用的资源。

    contains():判断某一个对象是否存在一级缓存中。

    flush():刷新一级缓存中的对象,使之与数据库保持同步。

    一级缓存主要是缓存实体对象,在save()方法执行时,会向session中保存一份。另外,get()和load()加载数据时,如果缓存中存在数据的话,就直接在缓存中取,如果不存在,再去数据库中取。另外,因为一级缓存是缓存实体对象的,所以当save方法执行完之后,如果用hql语句查询对象,那么这个查询也是从session缓存中获取的。

/**
* 在同一个session中发出两次load查询
*/
public void testCache1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());

//不会发出查询语句,load使用缓存
student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());

session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 在同一个session中先调用save,再调用load查询刚刚save的数据
*/
public void testCache6() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = new Student();
student.setName("张三");
Serializable id = session.save(student);
student = (Student)session.load(Student.class, id);
//不会发出查询语句,因为save支持缓存
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 在同一个session中发出两次get查询
*/
public void testCache2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.get(Student.class, 1);
System.out.println("student.name=" + student.getName());

//不会发出查询语句,get使用缓存
student = (Student)session.get(Student.class, 1);
System.out.println("student.name=" + student.getName());

session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}


二级缓存

    二级缓存是SessionFactory范围内的缓存,它缓存的数据是供一个SessionFactory中的所有Session共享的。二级缓存通常是使用插件来完成的,常用的插件有以下几种:

    EHCache org.hibernate.cache.EhCacheProvider

    OSCache org.hibernate.cache.OSCacheProvider

    SwarmCache org.hibernate.cache.SwarmCacheProvider

    JBossCache org.hibernate.cache.TreeCacheProvider

    在使用二级缓存时,是需要在配置文件中配置这些插件的。首先是在hibernate.cfg.xml中配置二级缓存,指定相应实体使用二级缓存,然后配置二级缓存的配置文件,这样就可以使用二级缓存了。

<!-- 配置缓存提供商 -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

<!-- 启用二级缓存,这也是它的默认配置 -->
<property name="hibernate.cache.use_second_level_cache">true</property>

<mapping resource="com/bjpowernode/hibernate/Student.hbm.xml"/>
<mapping resource="com/bjpowernode/hibernate/Classes.hbm.xml"/>

<!--
指定Student使用二级缓存
-->
<class-cache class="com.bjpowernode.hibernate.Student" usage="read-only"/> 缓存的策略
<ehcache>
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000"   最多缓存对象的个数
eternal="false"               缓存中的对象是否是永远不变的
timeToIdleSeconds="120"       可以操作对象的时间
timeToLiveSeconds="120"       缓存中对象的生命周期
overflowToDisk="true"         内存满了之后,是否缓存到硬盘上
/>

<cache name="com.bjpowernode.hibernate.Student"
maxElementsInMemory="100"
eternal="false"
timeToIdleSeconds="10000"
timeToLiveSeconds="10000"
overflowToDisk="true"
/>

</ehcache>
/**
* 开启二级缓存
*
* 在两个session中发load查询
*/
public void testCache1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}

try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.load(Student.class, 1);

//不会发出查询语句,因为配置二级缓存,session可以共享二级缓存中的数据
//二级缓存是进程级的缓存
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}

}

/**
* 开启二级缓存
*
* 在两个session中发get查询
*/
public void testCache2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.get(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}

try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.get(Student.class, 1);

//不会发出查询语句,因为配置二级缓存,session可以共享二级缓存中的数据
//二级缓存是进程级的缓存
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}

}


二级缓存也有几个方法来管理:
    evict(Class arg0, Serializable arg1):将某个类指定ID的持久化对象从二级缓存中清除,释放其占用的资源。

    evict(Class arg0):将指定类的所有持久化对象都从二级缓存中清除,释放其占用的资源。

    evictCollection(String arg0):将指定类的所有持久化对象的集合从二级缓存中清除,释放其占用的资源。

    二级缓存没有特定的储存位置,是根据配置文件中配置的位置来缓存的。

    如何判断数据是从缓存中读取,还是从数据库中读取呢?可以通过是否发SQL语句来判断。在hibernate.cfg.xml中配置showsql的属性为true,这样在执行数据库操作时就会发出SQL语句。如果是操作的数据库,那么就会发出相应的语句,如果是操作的缓存,那么就不会发出SQL语句。

总结

    在一级缓存和二级缓存都启用的情况下,首先对实体的操作会缓存在一级缓存中,同时也会缓存在二级缓存中一份。当再次操作数据时,先查看需要操作的对象是否在一级缓存中,如果有则直接读取;如果没有则查看是否在二级缓存中,如果有则直接读取,如果没有则操作数据库,这时就要发出SQL语句。一级缓存是缓存在内存中的,它的缓存的对象是没有生命周期的;二级缓存是根据配置文件配置的,同样在配置文件中可以配置缓存对象的缓存时间。一级缓存和二级缓存在对数据库减压方面都有很大的作用,同时也要注意缓存数据的更新问题和并发问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hibernate 缓存机制