2013-02-20 63 views
8

我们在我们的项目中使用hibernate4ehcache。我们主要研究不可变的对象,所以缓存是一个非常适合我们应用的功能。尝试启用查询缓存,我们遇到了以下问题:Hibernate缓存:缓存查询返回的对象是否存储在L2缓存中?

假设我们有以下的实体:

@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设置为约3/4的狗timeToLive。这里的情景(请纠正我,如果我犯了一个错误的假设):

  1. 第一次查询称为(假设缓存为空),它是执行和返回的狗实例存储在第二级缓存。另外,Dog ID保存在查询缓存中。
  2. 第二次调用查询(Dog ID位于查询缓存中,Dog对象位于L2缓存中)时,一切正常。查询缓存返回id,Dog从L2中获取。
  3. 当查询缓存过期(但L2缓存仍然有效)时,查询将重新运行并缓存Dog ID。
  4. 现在二级缓存过期,Dog对象和所有对象都从缓存中逐出。查询缓存仍然具有缓存的ids,因此hibernate会一个一个获取Dog对象,这需要永久。

第三个问题是纠缠我。查询缓存在数据库中失效并重新运行,获取Dog对象,但Dog对象未在L2缓存中更新。它看起来像查询只更新查询缓存中的狗标识符,而不是二级缓存。

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

+0

您可以启用读/写入缓存模式,以便EHCache在更新时处理它。 – Phani 2013-07-24 17:21:22

+0

该实体是只读的,所以这不会有帮助。 – 2013-07-25 10:08:53

回答

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 

希望它可以帮助

+0

你什么时候建议我应该清理缓存?如果我在每次请求之前清除它,根本没有任何意义。 – 2013-07-25 10:28:35

+0

我对计划事件做了干净的缓存(由于项目事实)。 所以不时(预定的时间来自系统团队)我们清理缓存 – victoriza 2013-07-25 11:01:44

+0

因此,这取决于您的项目数据库大小和使用情况。如果没有准确的数据,猜测是不可能的 – victoriza 2013-07-25 11:02:57

2

见二级缓存为对象/ POJO的你指定越来越缓存。但是查询缓存是为特定查询创建的。因此,当你的查询缓存被更新时,两者都是不相关的,二级缓存不会更新,这似乎很自然。这就是为什么它们都有不同的配置。您可以参考Hibernate Documentationthis linkthis link可能会帮助您了解事情。

+0

我知道这些是两个不同的缓存,但查询缓存使用域缓存通过ID检索对象,对不对?这导致了所描述的问题,到目前为止我还没有找到任何解决方案。 – 2013-07-25 19:26:08

+0

因此,这个答案不能解决所描述的问题。 – 2013-07-26 09:23:12

+0

朋友你需要接受这个设计。这不是问题,这是为此设计的。 – 2013-07-26 09:32:20

0

在我的情况下,我禁用休眠中的最小put设置,然后查询缓存将在每次发布SQL时自动更新所有相关的二级缓存。

我认为这是解决你的问题“以强制查询也更新L2缓存”(这也来烦我很长一段时间......)

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