Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Hibernate缓存:缓存查询返回的对象是否存储在二级缓存中?_Java_Hibernate_Ehcache - Fatal编程技术网

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

Java Hibernate缓存:缓存查询返回的对象是否存储在二级缓存中?,java,hibernate,ehcache,Java,Hibernate,Ehcache,我们在项目中使用了hibernate4和ehcache。我们主要处理不可变的对象,因此缓存是一个非常适合我们的应用程序的特性。尝试启用查询缓存时,我们遇到以下问题: 假设我们拥有以下实体: @Entity @Table(name = "DOGS") @Immutable @Cache(usage = CacheConcurrencyStrategy.READ_ONLY) class Dog { @Id @Column Long id; @Column String name;

我们在项目中使用了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。以下是场景(如果我的假设错误,请纠正我):

  • 第一次调用查询时(假设缓存为空),将执行查询并将返回的狗实例存储在二级缓存中。此外,狗ID存储在查询缓存中
  • 第二次调用查询时(狗ID在查询缓存中,狗对象在二级缓存中),一切正常。查询缓存返回ID,狗从L2中取出
  • 当查询缓存过期(但二级缓存仍然有效)时,查询将重新运行并缓存狗ID
  • 现在,狗对象的二级缓存过期,所有对象都从缓存中退出。查询缓存仍然缓存了ID,因此hibernate将一个接一个地获取Dog对象,这将花费很长时间
  • 第三点困扰着我。查询缓存失效并在数据库上重新运行,获取了Dog对象,但二级缓存中没有更新Dog对象。看起来查询只更新了查询缓存中的狗ID,而没有更新二级缓存中的狗ID


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

    我曾尝试过这种方法,并在过去为我清理二级缓存

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

    希望它能有所帮助

    查看二级缓存是针对您指定用于获取缓存的对象/POJO的。但查询缓存是为特定查询创建的。所以,当查询缓存更新时,二级缓存将不会得到更新,这似乎很自然。这就是为什么它们都有不同的配置。您可以参考或帮助您理解事情。

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

    我认为这就是你的问题“强制查询同时更新二级缓存”的解决方案(这也让我很长时间感到困扰……)

    
    
    您可以启用读/写缓存模式,以便EHCache在更新时对其进行处理。该实体是只读的,因此没有帮助。您建议我何时清理缓存?如果我在每次请求之前都清除它,那么拥有一个缓存就毫无意义了。我在计划的事件中清除了缓存(由于项目事实)。因此,我们会不时清理缓存(计划时间由系统团队确定),因此这实际上取决于您的项目数据库大小和使用情况。如果没有准确的数据,就不可能猜测问题的关键是我不想添加任何退出缓存的启发式算法,因为我不能100%确定所描述的情况不会发生。我知道这是两个不同的缓存,但是查询缓存使用域缓存按id检索对象,对吗?这导致了所描述的问题,到目前为止我还没有找到任何解决方案。朋友,你需要接受这个设计。这不是一个问题,这是这样设计的。我希望你访问我提供的链接。我会让你知道,如果我遇到的东西,可能会帮助你解决这个问题。我知道这些链接,我已经搜索了很多,以找到这个问题的答案:)然而,如果这是工作的设计,那么设计真的很糟糕。假设缓存的查询返回1000个ID,那么1000个选择将被发送到数据库。:-)这是这样的:0
    <property name="hibernate.cache.use_minimal_puts" value="false"/>