在Grails应用程序中休眠二级缓存

Dón*_*nal 39 grails caching hibernate grails-orm

第一部分

在Grails应用程序中,我了解您通过添加为每个域类启用第二级缓存

static mapping {
  cache true
}
Run Code Online (Sandbox Code Playgroud)

默认情况下,第二级缓存仅在get()调用时使用,但也可以通过添加cache true到查询中用于条件查询和动态查找器.

但是,我仍然不确定我是否理解查询缓存的工作原理.我最好的猜测是:

  • 每个域类都有单独的查询缓存,例如一个用于Book,另一个用于Author
  • Author.findByName('bob', [cache: true])执行类似查询之前,计算缓存键,该缓存键基于域类(作者),查询(findByName)和查询参数('bob').如果在作者查询缓存中找到该键,则返回缓存的结果而不是执行查询
  • 每当保存,删除或更新作者时,都会刷新作者查询缓存

在我们考虑返回Book实例的查询可以加入Author表之前,这似乎是合理的.在这种情况下,在保存,删除或更新作者时,有必要刷新Book和Author查询缓存.这让我怀疑可能只有一个查询缓存,并且只要保存了任何缓存的域类,它就会被清除?

第二部分

在Grails文档中,它提到了这一点

除了使用Hibernate的二级缓存来缓存实例的能力之外,您还可以缓存对象的集合(关联).

例如:

class Author {    

  static hasMany = [books: Book]

  static mapping = { 
    cache true        // Author uses the 2nd level cache
    books cache: true // associated books use the 2nd level cache
  } 
}

class Book {
  static belongsTo = [author: Author]

  static mapping = {
    cache true // Book uses the 2nd level cache
  }
}
Run Code Online (Sandbox Code Playgroud)

上面的配置是否有意义,即如果Author和Book本身使用二级缓存,那么使Author-Book关联也使用二级缓存有什么好处吗?

第三部分

最后,我读过这个建议有关使用2级查询缓存,这表明它应该只被用于不频繁变化的领域类.在任何情况下都不应该为get()操作启用第二级缓存,即任何人不会将以下内容添加到域类的任何原因

static mapping = {
  cache true // Book uses the 2nd level cache
}
Run Code Online (Sandbox Code Playgroud)

JB *_*zet 44

第1部分:

Hibernate做对了.查询缓存不是每个实体.除非您为查询设置特定区域,否则所有查询都会共享一个查询缓存区域.每次更新表时,都会更新时间戳缓存中的时间戳.每次执行查询时,将查询搜索的每个表的时间戳与缓存结果的时间戳进行比较.当然,只有当其时间戳比所有表时间戳更新时,才会返回缓存结果.

第2部分:

是的,这是有道理的.作者的缓存会记住ID为456的作者名称为"foo",出生日期为1975/07/19.仅记住存储在作者表中的数据.因此,缓存关联也很有用:在调用时author.getBooks(),Hibernate不会在获取作者的书籍集时进行额外的查询,而是从缓存中获取作者书籍的ID,然后从第二部分加载每本书级缓存.但请确保缓存书籍.

第3部分:

我可以想象几个原因:

  • 有这么多的实体,它们如此变化,以至于缓存命中数会非常低,而且二级缓存处理实际上比没有缓存的解决方案消耗更多的时间和内存
  • 应用程序是群集的,并且分布式二级缓存的成本和复杂性太高,以获得低增益
  • 其他非hibernate应用程序写入同一个数据库,因此缓存有很大的风险返回过时的数据,这是不可接受的
  • 没有二级缓存,一切都很顺利,没有理由让应用程序比它更复杂.

  • 我证实你的理论. (3认同)