Hibernate 一级缓存与查询缓存

2024-01-04

一级缓存与hibernate中的查询缓存不同吗?我看过有关一级缓存和查询缓存的文章,所以我很困惑。


是的,是不同的东西。 就像 Lee Chee Kiam 所说,一级缓存默认启用,您无法禁用它。 基本上这是 Hibernate 第一次放置获取的实体的地方,因此同一对象的第二次查询不会实例化新对象,甚至可以避免通过 ID 进行查询。一个关于这个的例子here http://howtodoinjava.com/2013/07/01/understanding-hibernate-first-level-cache-with-example/.

//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

我们可以说一级缓存是 Hibernate 的实现身份映射 http://martinfowler.com/eaaCatalog/identityMap.html图案。

查询缓存与实体严格相关,它在搜索条件和满足特定查询过滤器的实体之间建立关联(来自here http://vladmihalcea.com/how-does-hibernate-query-cache-work/)。 查询缓存仅将查询的原始结果作为主键(在 hibernate 中称为 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 的人员是否符合限制。 在这种情况下,您将避免查询的成本(在这种情况下几乎为零,但可能是带有连接等的昂贵查询),但您仍然会访问数据库来查询人员(现在通过 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 的 Person 对应的对象。

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

一些解释取自于此很棒的帖子 http://blog.jhades.org/setup-and-gotchas-of-the-hibernate-second-level-and-query-caches/你应该读一下这个好答案 https://stackoverflow.com/a/1998867/3517383 too.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Hibernate 一级缓存与查询缓存 的相关文章

随机推荐