Hibernate一级缓存与查询缓存

5

在Hibernate中,一级缓存和查询缓存有何不同?我看到过提到一级缓存和查询缓存的文章,所以有些困惑。

2个回答

11

是的,它们是不同的东西。 就像李志健说的,第一级缓存默认启用且无法禁用。 基本上,这是Hibernate第一次放置获取的实体的地方,所以对同一对象的第二个查询不会实例化新对象,甚至在按ID查询时也避免了查询。关于这个的一个例子在这里

//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对IdentityMap模式的实现。

查询缓存严格与实体相关,并将搜索条件和符合该特定查询过滤器的实体之间建立关联(来自这里)。 查询缓存仅保存查询的原始结果作为主键,在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的人员与限制条件匹配。 在这种情况下,您将避免查询成本(在这种情况下几乎为零,但可能是一个具有联接等昂贵查询的查询),但仍将访问数据库以查询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的Person对象的原始数据构建对象。

查询缓存和第二级缓存用于具有多次读取和很少或零次更新的实体。由于每种类型的缓存都存在不一致性的问题。因此,Hibernate需要使缓存无效或刷新缓存(如果您有集群缓存,则包括复制)。如果更新频繁,您将不断使缓存无效,而这会带来更多的负面影响。

一些解释摘自这篇优秀文章,您还应该阅读这个良好答案


6

默认情况下启用了一级缓存,且基于每个会话。查询缓存未启用,默认情况下在多个会话之间共享,并且应始终与二级缓存一起使用。

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接