zoukankan      html  css  js  c++  java
  • hibernate笔记--缓存机制之 二级缓存(sessionFactory)和查询缓存

    二级缓存(sessionFactory):

      Hibernate的二级缓存由SessionFactory对象管理,是应用级别的缓存。它可以缓存整个应用的持久化对象,所以又称为“SessionFactory缓存”.

      hibernate二级缓存中的缓存对象可以被整个应用的Session对象共享,即使关闭当前Session对象,新建的Session对象仍可使用。使用Hibernate的二级缓存之后查询数据,Session对象会首先在以及缓存中查找有无缓存数据被命中。如果没有,则查找二级缓存。如果有,则直接返回所命中的数据;否则查询数据库

      下面介绍在hibernate中如何开启和使用二级缓存:

      1.在hibernate.cfg.xml中开启二级缓存,并且配置cache.region.factory_class:

    <!-- 开启二级缓存 -->
        <property name="cache.use_second_level_cache">false</property>
        <!-- 配置cache.region.factory_classs -->
        <property name="cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>

      2:导入第三方jar包,(下载hibernate资源包,会在liboptionalehcache文件夹下找到相关jar包):

      3.在src目录下,新建ehcache.xml.或在hibernate资源包的projectetc目录下找到该文件,copy到src目录下:

        ehcache.xml:

    <ehcache>
        <diskStore path="java.io.tmpdir"/>
        <!-- 
            maxElementsInMemory:设置存放对象数量的最大值
            eternal:设置是否永久存储
            timeToIdleSeconds:设置对象的空闲时间
            timeToLiveSeconds:设置对象的存活时间
            overflowToDisk:内存溢出是否写入磁盘
         -->
        <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="true"
            />
        <cache name="sampleCache1"
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="300"
            timeToLiveSeconds="600"
            overflowToDisk="true"
            />
        <cache name="sampleCache2"
            maxElementsInMemory="1000"
            eternal="true"
            timeToIdleSeconds="0"
            timeToLiveSeconds="0"
            overflowToDisk="false"
            /></ehcache>

      4:在需要使用二级缓存的实体类的hbm.xml文件中设置,或在hibernate.cfg.xml中指定需要使用二级缓存的实体类:

        以上一节的Book和Category为例,如果我需要开启Book的二级缓存:

          *在Book.hbm.xml文件中的class标签下,添加一个标签:

          <cache usage="read-only"/>

          *或在hibernate.cfg.xml的mapping属性下面,添加:

          <class-cache usage="read-only" class="com.wang.pojo.Book"/>

        关于usage的取值,有以下几种:

    只读缓存(read-only):如果应用程序需要读取一个持久化类的实例,但是并不打算修改它们,可以使用read-only缓存。这是最简单,也是实用性最好的策略.

    读/写缓存(read-write): 如果应用程序需要更新数据,可能read-write缓存比较合适。如果需要序列化事务隔离级别,那么就不能使用这种缓存策略。

    不严格的读/写缓存(nonstrict-read-write):如果程序偶尔需要更新数据(也就是说,出现两个事务同时更新同一个条目的现象很不常见),也不需要十分严格的事务隔离,可能适用nonstrict-read-write缓存。

    事务缓存(transactional):  transactional缓存策略提供了对全事务的缓存,仅仅在受管理环境中使用。它提供了Repeatable Read事务隔离级别。对于经常被读但很少修改的数据,可以采用这种隔离类型,因为它可以防止脏读和不可重复读这类的并发问题。

    以上配置工作全部完成,我们来用代码,感受一下二级缓存的存在:

          Session session=HibernateUtil.getSession();
            Book book =(Book) session.get(Book.class,1);
            System.out.println(book.getName());
            session.beginTransaction().commit();
            session.close();
            System.out.println(book.getName());

    在这段代码中,我先查询了一下id=1的Book信息,然后关闭了session对象,很明显一级缓存肯定是不存在了,然后我再次打印book的name,我们先看看控制台的打印信息:

    神奇的是发生了,居然没有报错,而且打印出了book的name,这就是二级缓存的作用.现在我们再来看看开头的第二段内容,就一目了然了.

    hibernate二级缓存中的缓存对象可以被整个应用的Session对象共享,即使关闭当前Session对象,新建的Session对象仍可使用。使用Hibernate的二级缓存之后查询数据,Session对象会首先在以及缓存中查找有无缓存数据被命中。如果没有,则查找二级缓存。如果有,则直接返回所命中的数据;否则查询数据库

    查询缓存:

      查询缓存缓存的是查询出来的实体的部分属性结果集和实体的ID(注意这里不是实体).关于查询缓存和二级缓存的同时和分开使用的情况,网络上这一段解释的比较好,这里直接引用了:

    当只是用Hibernate查询缓存而关闭二级缓存的时候: 
      第一:如果查询的是部分属性结果集: 那么当第二次查询的时候就不会发出SQL,直接从Hibernate查询缓存中取数据;
      第二:如果查询的是实体结果集eg(from Student) ,首先Hibernate查询缓存存放实体的ID,第二次查询的时候就到Hibernate查询缓存中取出ID 一条一条的到数据库查询,这样,将发出N 条SQL造成了SQL泛滥。

    当都开启Hibernate查询缓存和二级缓存的时候:
      第一:如果查询的是部分属性结果集: 这个和上面只是用Hibernate查询缓存而关闭 二级缓存的时候一致,因为不涉及实体不会用到二级缓存;
      第二:如果查询的是实体结果集eg(from Student),首先Hibernate查询缓存存放实体的ID,第二次查询的时候,就到Hibernate查询缓存中取出ID,到二级缓存区找数据,如果有数据,就不会发出SQL;如果都有,一条SQL都不会发出,直接从二级缓存中取数据。

    下面介绍如何开启和使用查询缓存:

      1.在hibernate.cfg.xml中.添加一个标签语句:

       <!-- 开启查询缓存 -->
        <property name="cache.use_query_cache">true</property>

      2.在代码中添加query.setCachemodel(true);

        List<Book> list =(List) session.createQuery("from Book")
                                  .setCacheable(true)//使用查询缓存
                                  .list();
            System.out.println(list.get(0).getName());
            session.beginTransaction().commit();
            session.close();
            System.out.println(list.get(0).getName());

    这里使用了list(),查询所有Book信息,关闭session以后再次打印list中的内容,依然能打印出来,不会报错,这就是查询缓存的使用.

    注意:

      查询缓存的生命周期与Session无关(可以跨Session查询),当查询关联的表发生改变,那么查询缓存的生命周期结束(delete、update、modify)

      查询缓存是专为Query的list方法设计的。对于iterate()方法,无论是查询对象属性还是对象本身,查询缓存用与不用都没有区别!

  • 相关阅读:
    Git ---游离状态下的commit 分支切换与找回,commit之后无法找到历史记录
    mybatis异常invalid comparison: java.util.Date and java.lang.String
    Spring的注解@Qualifier
    Spring @Bean注解的使用
    Java的IO系统
    linkin大话面向对象--GC和jar包
    linkin大话面向对象--闭包和回调
    linkin大话面向对象--内部类
    linkin大话面向对象--枚举
    linkin大话面向对象--接口
  • 原文地址:https://www.cnblogs.com/fingerboy/p/5258930.html
Copyright © 2011-2022 走看看