在Grails应用程序中,我了解到您可以通过添加以下方式为每个域类启用二级缓存
static mapping { cache true }
默认情况下,仅在get()调用时使用二级缓存,但也可以通过添加cache true到查询将其用于条件查询和动态查找器。
get()
cache true
但是,我仍然不确定我是否了解查询缓存的工作原理。我最好的猜测是:
Author.findByName('bob', [cache: true])
在我们认为返回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 } }
上面的配置是否有意义,即如果Author和Book本身使用的是二级缓存,那么使Author-Book关联也使用二级缓存有什么好处吗?
最后,我读过这个建议有关使用2级查询缓存,这表明它应该只被用于不频繁变化的领域类。是否有任何情况下不应为get()操作启用二级缓存,即为什么不将以下内容添加到域类的任何原因?
static mapping = { cache true // Book uses the 2nd level cache }
第1部分:
Hibernate做正确的事。查询缓存不是每个实体的。除非您为查询设置特定的区域,否则所有查询共享一个查询高速缓存区域。每次更新表时,都会在时间戳缓存中更新其时间戳。每次执行查询时,会将查询搜索到的每个表的时间戳与缓存结果的时间戳进行比较。当然,仅当缓存的时间戳比所有表的时间戳都近时才返回缓存的结果。
第2部分:
是的,这很有道理。作者的高速缓存记住ID为456的作者的名称为“ foo”,出生日期为1975/07/19。只记住存储在作者表中的数据。因此,缓存关联也很有用:author.getBooks()Hibernate不会在调用时进行额外的查询来获取作者的书籍集,而是从其缓存中获取作者的书籍ID,然后从第二个缓存中加载每本书级缓存。不过,请确保缓存书籍。
author.getBooks()
第3部分:
我可以想象几个原因: