Hibernate缓存:缓存查询返回的对象是否存储在L2缓存中?

时间:2013-02-20 18:15:18

标签: java hibernate ehcache

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

假设我们有以下实体:

@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缓存中),一切正常。查询缓存返回id,并从L2获取Dog。
  3. 当查询缓存过期(但L2缓存仍然有效)时,查询会重新运行并缓存Dog ID。
  4. 现在,L2缓存为Dog对象过期,所有对象都从缓存中逐出。查询缓存仍然具有缓存的ID,因此hibernate逐个获取Dog对象 ,这需要永远。
  5. 第三点是烦我。查询缓存无效并在数据库上重新运行,获取Dog对象,但Dog对象未在L2缓存中更新。看起来查询只更新了查询缓存中的dog ID,而不是L2缓存。

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

3 个答案:

答案 0 :(得分:2)

请参阅第二级缓存是指定用于获取缓存的Object / Pojos。但是为特定查询创建了查询缓存。因此,当您的查询缓存更新时,两者都是无关的并且二级缓存不会更新似乎很自然。这就是为什么两者都有不同的配置。您可以参考Hibernate Documentationthis linkthis link来帮助您了解事情。

答案 1 :(得分: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

希望有所帮助

答案 2 :(得分:0)

就我而言,我在hibernate中禁用了最小put设置,然后每次SQL发出时,查询缓存都会自动更新所有相关的二级缓存。

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

<property name="hibernate.cache.use_minimal_puts" value="false"/>