zoukankan      html  css  js  c++  java
  • 二级缓存

    1 对一级缓存和二级缓存分析:
    1.1  一级缓存:一级缓存是一个事务中的缓存,只发生在一个session打开之后关闭之前,一般一级缓存是不需要人工管理操作的,但是当应用程序中有时需要大批量更新信息时候也会出现OutOfMemoryException错误,Hibernate也提供了两种方式管理一级缓存:
    方法一:session.evict()
    此方法一般在执行删除某记录时候执行:
    Session. delete(user);
    Session. evict(user);
    方法二:session.clear()
    此方法用于将一级缓存全部清空。
    1.2 二级缓存的原理:Hibernate内部只支持一级缓存,表现在session打开关闭之前如果里面有同样的session.get()语句则不会出现第二次查询,不过这个有局限只能局限在sessin打开之后关闭之前;二级缓存突破了这一限制,在session关闭之后也能打开第二个session并在第二个里执行与第一个session里同样的session.get(),然而不通过二次查询数据库也能查到相应数据。
    1.3  Hibernate二级缓存的配置:
        (1) 设置Hibernate支持二级缓存功能:
    在hibernate.cfg.xml配置文件中添加属性:
    <property name=" cache.use_second_level_cache ">true</property>
    其实Hibernate默认的cache.use_second_level_cache值也是true,所以此属性用户可以不配置。
        (2) 设置二级缓存实现的提供商:
    在hibernate.cfg.xml配置文件中添加属性:
    <property name=" cache.provider_class "> org.hibernate.cache.OSCacheProvider
    </property>
    二级缓存的实现类有很多,好比:org.hibernate.cache.OSCacheProvider
       (3) 设置需要进行二级缓存的类:
    方法一
    在hibernate.cfg.xml中添加配置:
    <class-cache usage="read-only" class="cn.itcast.domain.User"/>
    注:使用策略usage的选项值有四种:
    ① read-only:如果你的应用程序只需读取一个持久类的实例,而无需对其修改,那么就可以对其进行只读缓存。这是最简单的,也是实用性最好的方法。甚至在群集中,它也能完美地运行。
    ② read-write:如果应用程序需要更新数据,那么读/写缓存比较合适。
    ③ nonstrict-read-write:如果应用程序只偶尔需要更新数据(也就是说,两个事物同时更新同一记录的情况很不常见),也不需要十分严格的事务隔离,那么比较适合使用非严格读/写策略。
    ④ transaction:事务策略提供了全事务的缓存支持,例如对JBoss TreeCache的支持。这样的缓存只能用于JTAG环境中,你必须指定为其transaction.manager_lookup_class属性。
    注意:class必须是完整的包括类包的类名。
    方法二:没每一个要进行二级缓存的类的映射文件设置:
    <class name="User" table="User">
       <cache usage="read-only"/>
         <id name="id">
           <generator class="native"/>
         </id>
        <component name="name">
          <property name="firstName" column="first_name"/>
          <property name="lastName" column="last_name"/>
        </component>
        <property name="birthday"></property>
     </class>
         注意:在<id>前定义<cache usage="read-only"/>如果映射文件中有集合类(如Set、Map、List等的)映射实体也要另行指定其cache的缓存同步策略并指定region(不过不包括component和  joined-subclass)
    另举例如下
      <set name="employees" cascade="save-update" inverse="true">
        <cache usage="read-only" region="Employee"/>
        <key column="dept_id"></key>
        <one-to-many class="Employee"/>
      </set>

    2  现在查看如下代码:
      User user=null;
      Session session=null;
      try
      {
        session=HibernateUtil.getSession();
        user=(User) session.get(User.class, id);
        System.out.println(user.getClass());
        //这里在session未关闭之前查询是利用一级缓存
      user=(User) session.get(User.class, id);
      System.out.println(user.getName());
      }
      finally
      {
        if(session!=null)
         session.close();
      }
      try
     { //之前的session关闭了,这里重新打开了一个新的session,这里查询利用的是二级缓存
        session=HibernateUtil.getSession();
        user=(User) session.get(User.class, id);
      }
      finally
      {
        if(session!=null)
        session.close();
      }
    2.1 检测二级缓存性能:
    (1) 在hibernate.cfg.xml配置一个属性:
    generate_statistics=true
    (2) 测试代码:
      public static void main(String[] args)
      {
        User user=addUser();
        getUser(user.getId());
       Statistics st=HibernateUtil.getSessionFactory().getStatistics();
        System.out.println("put"+st.getSecondLevelCachePutCount());
        System.out.println("hit"+st.getSecondLevelCacheHitCount());
        System.out.println("miss"+st.getSecondLevelCacheMissCount());
      }
    注意:以上代码作用是分别获取二级缓存中向map中存数据次数、命中数据次数、没命中数据次数。
        
    3  对二级缓存的人工管理:
     对二级缓存一般是不用管理的,都是有提供商和hibernate管理好的,不过也提供了几个控制二级缓存的方法:
     (1) HibernateUtil.getSessionFactory().evict(User.class);
        把二级缓存中User的所有实例清除掉包括继承它的子类实例;
     (2) HibernateUtil.getSessionFactory().evict(User.class, id);
        把二级缓存中通过id指定的User实例清除掉。
        
    4  增加对查询HQL查询的二级缓存功能:
     Query query=session.createQuery("from User where id>20");    
     像上面这样的查询语句,hibernate是默认不支持二级缓存的,因为每个查询都是有针对性的查询条件,下次查询的命中率不高,但是也是可以设置打开查询二级缓存的。
     打开步骤:
    (1). 在hibernate.cfg.xml中配置以下属性:
    <property name="cache.use_query_cache">true</property>
    注意:此属性Hibernate缺省的是false,所以必须配置为true。
    (2). 修改代码:
    static User query(int id)
    {
         Session session=null;
         session=HibernateUtil.getSession();
         Query query=session.createQuery("from User where id>20");
         query.setCacheable(true);
         User user=(User)query.uniqueResult();
         return user;
    }
     小结:
    1. Session的save()方法不适合native生成方式的主键。
    2. update,saveOrUpdate,list,iterator,get,load以及Query,Criteria都会填充二级缓存,但只是在查询缓存时候,Session的iterator.getLoad()会从二级缓存中取数据(iterator可能存在N+1此查询)
    3.Query.Criteria查询缓存由于命中率较低,所以Hibernate缺省时关闭的.
    4.SessionFactory中提供了evictXXX()方法用来清除缓存中的内容。
    5.统计信息打开generate_statics,用sessionFactory.getStatics()获取统计信息。
    转自:http://blog.163.com/zhangfei_jiayou/blog/static/56244178200983061742668/

  • 相关阅读:
    Git——新手入门与上传项目到远程仓库GitHub
    在树莓派上用Python控制LED
    树莓派从 DHT11 温度湿度传感器读取数据
    树莓派使用DHT11温湿度传感器(C语言程序)
    树莓派使用DHT11温湿度传感器(C语言)
    树莓派连接DHT11温湿度传感器(python)
    教你在树莓派使用上RTC实时时钟,不用再担心断电后时间归零的问题,开机后自动同步RTC时钟!!!
    【手把手教你树莓派3 (一)】装机
    【手把手教你树莓派3 (二)】 启动wifi模块
    Notes on Noise Contrastive Estimation and Negative Sampling
  • 原文地址:https://www.cnblogs.com/a1280055207/p/3173269.html
Copyright © 2011-2022 走看看