Hibernate缓存机制

Hibernate是一个持久层框架,经常访问物理数据库,为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据

Hibernate缓存主要分为三类

  1. 一级缓存
  2. 二级缓存
  3. 查询缓存

一级缓存又称session缓存,生命周期和session相同,周期较短。事务级别的缓存(我们提交一个事务后就把session关闭掉了)一级缓存是内置的,无法卸载的

get使用了一级缓存,用get获取数据的时候,首先检查缓存中是否有这个数据,如果有直接从缓存中取数据,如果没有查询数据库,同时将数据保存到缓存中
load也使用了一级缓存,同时还支持lazy,当load从数据库查询到数据时也会把数据放入缓存中

unique/list查询不会去查看缓存,但是list查询的实体对象将会放入缓存中。

iterate会执行查询id的操作(当需要对象的时候才会根据id去查找对象),当查询对象时,会检查缓存中是否存在。如果存在则从缓存中取数据。Iterate查询出来的对象也会放入缓存。

一级缓存存的是对象,属性是不会存的。
当然一级缓存的内存是有限的,什么数据都往里面存,所以我们需要管理一级缓存,通过flush(),clear(),evict()。

通过查阅Hibernate的API可以知道flush方法的主要作用就是清理缓存,强制数据库与Hibernate缓存同步,以保证数据的一致性。它的主要动作就是向数据库发送一系列的sql语句,并执行这些sql语句,但是不会向数据库提交。而commit方法则会首先调用flush方法,然后提交事务。这就是为什么我们仅仅调用flush的时候记录并未插入到数据库中的原因,因为只有提交了事务,对数据库所做的更新才会被保存下来。因为commit方法隐式的调用了flush,所以一般我们都不会显示的调用flush方法。


二级缓存又称为SessionFactory缓存,是进程级别的缓存,可以跨越Session存在,可以被多个Session所共享。支持集群。二级缓存是可选的。二级缓存的介质可以是内存或者硬盘
适合放到二级缓存中:

(1)经常被访问

(2)改动不大

(3)数量有限

(4)不是很重要的数据,允许出现偶尔并发的数据。

这样的数据非常适合放到二级缓存中的。

使用步骤:
1 . 在hibernate.cfg.xml中配置二级缓存

 
<property name="hibernate.cache.use_second_level_cache">trueproperty>    

<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProviderproperty>

在hibernate4以后的配置

<property name="cache.use_second_level_cache">trueproperty>
    <property name="cache.region.factory_class">
    org.hibernate.cache.ehcache.EhCacheRegionFactoryproperty>

2 . 导入ehcache.jar等相关jar包

3 . 将ehcahe.xml放入src下(在project→etc下找)



<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

       xsi:noNamespaceSchemaLocation="ehcache.xsd">

       <diskStore path="java.io.tmpdir" />

       <defaultCache 

              maxElementsInMemory="10000" 

              eternal="false" 

              timeToIdleSeconds="120" 

              timeToLiveSeconds="120" 

              overflowToDisk="true" 

              diskPersistent="false" 

              diskExpiryThreadIntervalSeconds="120" 

              memoryStoreEvictionPolicy="LRU" />

ehcache>

4.在类中指定或在(hibernate.cfg.xml)指定
类中(*.hbm.xml中)

<hibernate-mapping>
    <class name="cn.siggy.pojo.Book" table="book" catalog="hibernate4">
    
        <cache usage="read-only"/>

        <id name="id" type="java.lang.Integer">
            <column name="id" />
            <generator class="identity" />
        id>
        <property name="author" type="java.lang.String">
            <column name="author" />
        property>
        <property name="name" type="java.lang.String">
            <column name="name" />
        property>
        <property name="price" type="java.lang.Double">
            <column name="price" precision="22" scale="0" not-null="true" />
        property>
        <property name="pubDate" type="java.sql.Timestamp">
            <column name="pubDate" length="19" />
        property>
    class>

hibernate-mapping>

在hibernate.cfg.xml中指定类 配置

<class-cache usage="read-only" class="cn.siggy.pojo.Book"/>

5 .测试使用

@Test
    public void testGet(){
        Session session = HibernateUtil.getSession();
        Transaction tx = session.beginTransaction();

        Book book = (Book)session.get(Book.class, 1);
        //发出sql语句取数据
        System.out.println(book.getName());
        HibernateUtil.closeSession();


        session = HibernateUtil.getSession();
        System.out.println("---------");
        //因为有二级缓存,尽管上传查询关闭session但是这里没有发出sql语句
        book = (Book)session.get(Book.class, 1);
        System.out.println(book.getName());

        tx.commit();
        HibernateUtil.closeSession();
    }

查询数据的时候会先放入一级缓存,然后拷贝一份到二级缓存中去


查询缓存 在二级缓存的基础上来的,所以我们要使用查询缓存也就是要先配置好二级缓存。
在hibernate.cfg.xml中配置

    <property name="cache.use_query_cache">trueproperty>

hibernate的查询缓存是主要是针对普通属性结果集的缓存
如下测试使用

List list = session.createQuery("from Book")
                        .setCacheable(true)//使用查询缓存
                        .list();
        System.out.println(list.size());
        System.out.println("=========================");
        session.close();
        session = HibernateUtil.getSession();
        list = session.createQuery("from Book")
                .setCacheable(true)//使用查询缓存
                .list();
        System.out.println(list.size());

这里只会发出一条sql语句,之前说过list查询是不会去缓存中找的,但是会把查询到的对象放入到缓存。这里设置了查询缓存后list就会先去缓存中找数据,hibernate的查询缓存是主要是针对普通属性结果集的缓存

你可能感兴趣的:(hibernate4)