Hibernate缓冲策略 一

来源:互联网 发布:苹果6无法加入网络 编辑:程序博客网 时间:2024/04/29 02:39

一、hibernate为什么提供缓存?

什么是缓存?
在内存里开辟一块空间把本来应该存在硬盘里面的数据,存在这个空间里面,将来,需要这块数据的时候直接在内存中获取。这个就可以简单理解为缓存。
Hibernate 是一个持久层框架,经常访问物理数据库,为了减低应用程序对物理数据源的访问频次,从而提高应用程序的运行性能。
缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件,将同步缓存和物理数据源的数据。
那么,接下来,让我们来看看Hibernate的缓存原理是什么。

二、Hibernate 的缓存

首先,Hibernate的缓冲分两个级别:一级缓存 和 二级缓存。Hibernate一级缓存又称为 Session级别的缓存 ; 二级缓存又称为“SessionFactory的缓存”。由session ,和SessionFactory 中就可以看出,缓冲的作用范围不同。看两者的使用。

1、一级缓冲

Hibernate一级缓存又称为 Session级别的缓存 。Session的缓存是事务范围的缓存,所以一级缓冲的生命周期和session的生命周期是同步的。Session对象的生命周期通常对应一个数据库事务或者一个应用事务。在一级缓存中,持久化类的每个实例都具有唯一的OID。

在同一个session中,我们两次使用load来加载同一个对象,来看一级缓存:

@Test publicvoid cache1Test(){       Session s=sessionFactory.openSession();       s.beginTransaction();       Person person=(Person)s.load(Person.class, 1);       System.out.println(person.getName());       //因为Session存在缓冲,所以第二次查询直接在session中取       Person person2=(Person)s.load(Person.class, 1);       System.out.println(person2.getName());       s.getTransaction().commit();    }

结果是只发出一条SQL语句,是第一个查询的sql语句,第二次查询直接使用的session缓冲中的数据对象。
这就是一级缓冲,只能用在同一个session中,不能跨session来取值,那要是需要跨session取值,怎么办呢?
对了,就是sessionFactory级别的缓冲,就像是sessionFactory管理所有的session一样,这里的二级缓冲就跳出来session的小圈子,可以供所有的session来取值。

2、二级缓存。

二级缓存又称为“SessionFactory的缓存”。是SessionFactory级别的缓冲,由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此Hibernate二级缓存是进程范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。

二级缓存是可选的,是一个可配置的第三方插件,默认下SessionFactory不会启用这个插件,如果我们需要使用二级缓冲,就事先需要开启。

第一、开启缓存

我们需要在我们的hibernate.cfg.xml中开启我们的二级缓冲,如下:

<!-- 开启缓冲 --><property name="hibernate.cache.use_second_level_cache">true</property><!--指定是哪个二级缓冲--><property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property><!-- 使用查询二级缓冲 --><propertyname="hibernate.cache.use_query_cache">true</property>

第二:指明那个实体类需要使用缓冲

我们需要指明那个实体类需要使用缓冲,这里有两种配置,一种是xml配置,一种是Annotation的配置,分别如下:

Annotation的配置如下:

@Entity@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)@Table(name="p_person")public class Persion{}

Xml的配置也有两种,一种是在各自的hbm文件配置,一种是在cfg中配置,
hbm文件的配置如下:

<class name="Person" table="t_person">        <cache usage="read-write"/>        <id name="id">        ……</class>

cfg文件的配置如下:

<!-- 指定Student使用二级缓存     --><class-cache class="com.hibernate.Persion" usage="read-only"/>

第三:需要提供第三方的cache。

其实二级缓冲并不是由Hibernate来提供,是由第三方提供的缓冲插件,通常有以下几种第三方缓冲插件:

  • EhCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,对Hibernate的查询缓存提供了支持。
  • OSCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,提供了丰富的缓存数据过期策略,对Hibernate的查询缓存提供了支持。
  • SwarmCache:可作为集群范围内的缓存,但不支持Hibernate的查询缓存。
  • JBossCache:可作为集群范围内的缓存,支持事务型并发访问策略,对Hibernate的查询缓存提供了支持。

默认hibernate使用的是ehcache。默认的配置如下:

<defaultCache        maxElementsInMemory="10000"        eternal="false"        timeToIdleSeconds="120"        timeToLiveSeconds="120"        overflowToDisk="true"        />

到这里配置结束,我们来进行测试。

 @Test    publicvoid findTesterjihuanchong(){        Sessions=sessionFactory.openSession();        s.beginTransaction();        Personperson=(Person)s.load(Person.class, 1);        System.out.println(person.getName());        s.getTransaction().commit();        s.close();           // 另起一个session          Sessions2=sessionFactory.openSession();        s2.beginTransaction();        // 不会发SQL语句,读取的是二级缓存中的数据        Personperson2=(Person)s2.load(Person.class, 1);        System.out.println(person2.getName());        s2.getTransaction().commit();        s2.close();    }

结果是:只有第一个session中发送了一条SQL语句,第二个session中没有发送。

以上是Hibernate的 一级缓存和二级缓存的介绍,其实 Hiberante还有第三种缓存:查询缓存。什么是查询缓存?查询缓冲和一级,二级缓存的区别是什么,将在下篇博客中说明。

0 0
原创粉丝点击