8

我们在项目中使用hibernate4ehcache。我们主要处理不可变对象,因此缓存是一个非常适合我们应用程序的功能。在尝试启用查询缓存时,我们遇到了以下问题:

假设我们有以下实体:

@Entity 
@Table(name = "DOGS")
@Immutable 
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
class Dog {
  @Id @Column
  Long id;
  @Column
  String name;
}

和查询:

Criteria criteria = session.createCriteria(Dog.class);
criteria.add(Restrictions.in("id", ids));
criteria.setCacheable(true);

查询缓存 timeToLive 设置为 Dog timeToLive 的 3/4 左右。这是场景(如果我做出错误的假设,请纠正我):

  1. 第一次调用查询时(假设缓存为空),它被执行,返回的 Dog 实例存储在二级缓存中。此外,Dog id 存储在查询缓存中。
  2. 第二次调用查询(Dog id 在查询缓存中,Dog 对象在 L2 缓存中),一切正常。查询缓存返回 ids 并且从 L2 获取 Dogs。
  3. 当查询缓存过期(但二级缓存仍然有效)时,查询重新运行并缓存 Dog id。
  4. 现在,Dog 对象的 L2 缓存到期,所有对象都从缓存中逐出。查询缓存仍然缓存了 id,因此 hibernate 会一个一个地获取 Dog 对象,这需要很长时间。

第三点困扰着我。查询缓存失效并在数据库上重新运行,获取 Dog 对象,但 Dog 对象未在 L2 缓存中更新。看起来查询只更新了查询缓存中的狗 ID,而不是 L2 缓存。

有没有办法强制查询也更新 L2 缓存?也许这种情况要以不同的方式处理?

4

3 回答 3

2

请参阅二级缓存适用于您指定用于缓存的对象/Pojo。但是查询缓存是为特定查询创建的。因此,当您的查询缓存更新时,两者都不相关并且二级缓存不会更新似乎很自然。这就是为什么它们都有不同的配置。您可以参考Hibernate 文档此链接,或者此链接可以帮助您理解事物。

于 2013-07-25T12:04:25.603 回答
1

我尝试过这个并在过去为我工作以清理 L2 缓存

//clear the cache entity
sf.getCache().evictEntity(Dog.class,12345); //Entity with 12345 id

//or clear a collection 
sf.getCache().evictCollection("com.package.Dog.getCol",12345); //Collections
//Note: the collection contains the name of the fully qualified class.

//then, run the query

希望能帮助到你

于 2013-07-25T09:58:52.627 回答
0

在我的例子中,我禁用了休眠中的最小放置设置,然后查询缓存将在每次 SQL 发出时自动更新所有相关的二级缓存。

我认为这是您问题“强制查询也更新 L2 缓存”的解决方案(这也困扰了我很长时间.....)

<property name="hibernate.cache.use_minimal_puts" value="false"/>
于 2015-05-12T01:43:23.113 回答