【问题标题】:Hibernate First level Cache vs Query CacheHibernate 一级缓存与查询缓存
【发布时间】:2013-10-31 05:45:08
【问题描述】:

一级缓存与休眠中的查询缓存不同吗?我看过文章提到一级和查询缓存,所以我很困惑。

【问题讨论】:

    标签: hibernate query-cache first-level-cache


    【解决方案1】:

    一级缓存默认启用,并且基于每个会话。查询缓存默认不启用,在多个会话之间共享,应始终与二级缓存结合使用。

    要启用查询缓存,应使用以下属性:

    hibernate.cache.use_second_level_cache=true
    hibernate.cache.use_query_cache=org.hibernate.cache.EhCacheProvider
    hibernate.cache.use_query_cache=true
    

    【讨论】:

      【解决方案2】:

      是的,是不同的东西。 就像 Lee Chee Kiam 所说,一级缓存默认启用,您不能禁用它。 基本上它是 Hibernate 第一次放置获取的实体的地方,因此对同一对象的第二次查询不会实例化新对象,甚至可以避免查询,如果它是按 ID 进行的。一个关于这个here的例子。

      //Open the hibernate session
      Session session = HibernateUtil.getSessionFactory().openSession();
      session.beginTransaction();
      
      //fetch the department entity from database first time
      DepartmentEntity department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
      System.out.println(department.getName());
      
      //fetch the department entity again
      department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
      System.out.println(department.getName());
      
      session.getTransaction().commit();
      HibernateUtil.shutdown();
      
      Output:
      
      Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ where department0_.ID=?
      Human Resource
      Human Resource
      

      我们可以说一级缓存是IdentityMap 模式的Hibernate 实现。

      查询缓存与实体严格相关,它在搜索条件和满足特定查询过滤器的实体之间建立关联(来自here)。 查询缓存仅将查询的原始结果作为主键保存,用休眠方式来说,就是 id。 它不包含实际的水合物体

      查询缓存是如何工作的?

      假设我们有以下条件查询:

      session.createCriteria(Person.class)
          .add( Restrictions.eq("firstName", "Joey")
          ).setCacheable(true);
      

      查询缓存在概念上看起来像一个哈希映射,其中键由查询文本和参数值组成,值是与查询匹配的实体 ID 的列表

      *----------------------------------------------------------*
      |                       Query Cache                        |                     
      |----------------------------------------------------------|
      | ["from Person where firstName=?", ["Joey"] ] -> [1, 2] ] |
      *----------------------------------------------------------*
      

      因此,下次我们执行相同的条件查询时,Hibernate 将查看该哈希映射并确定 ID 为 1 和 2 的 Persons 匹配限制。 在这种情况下,您将避免查询的成本(在这种情况下几乎为零,但可能是带有连接等的昂贵查询),但您仍然会访问数据库以查询 Persons(现在通过 id 是什么非常快)用于构造 Person 对象。 查询缓存经常与二级缓存一起使用,这需要第三方实现,例如 Ehcache 或 infinispan。

      二级缓存存储实体数据,但不存储实体本身。数据以“脱水”格式存储,看起来像哈希映射,其中键是实体 ID,值是原始值列表。 以下是二级缓存内容的外观示例:

      *-----------------------------------------*
      |          Person Data Cache              |
      |-----------------------------------------|
      | 1 -> [ "Joey" , "Q" , "Public" , null ] |
      | 2 -> [ "Joey" , "D" , "Public" ,  1   ] |
      | 3 -> [ "Sara" , "N" , "Public" ,  1   ] |
      *-----------------------------------------*
      

      所以,查询缓存会为我们提供 id 1 和 2,然后 Hibernate 将使用二级缓存中对应于 id 1 和 2 的 Persons 的原始数据构造对象。

      查询缓存和二级缓存用于具有多次读取和很少或零更新的实体。因为众所周知的问题是每种类型的缓存不一致。因此,Hibernate 将需要使缓存无效或刷新(如果您有集群缓存,则包括复制)。随着许多更新,您将不断使缓存失效,并且弊大于利。

      一些解释来自这个great post,你也应该阅读这个good answer

      【讨论】:

        猜你喜欢
        • 2014-11-28
        • 2011-12-18
        • 2014-06-25
        • 2018-11-18
        • 1970-01-01
        • 2014-06-20
        • 2013-12-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多