Hibernate缓存机制

来源:互联网 发布:安大略理工大学知乎 编辑:程序博客网 时间:2024/06/16 18:30

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">true</property>    <!--设置缓存的类型,设置缓存的提供商--><property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

在hibernate4以后的配置

<property name="cache.use_second_level_cache">true</property>    <property name="cache.region.factory_class">    org.hibernate.cache.ehcache.EhCacheRegionFactory</property>

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

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

<?xml version="1.0" encoding="UTF-8"?><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">true</property>

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

List<Book> 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的查询缓存是主要是针对普通属性结果集的缓存

原创粉丝点击