使用 Hibernate + Spring 进行缓存 - 一些问题

Posted

技术标签:

【中文标题】使用 Hibernate + Spring 进行缓存 - 一些问题【英文标题】:Caching with Hibernate + Spring - some Questions 【发布时间】:2011-07-21 07:07:15 【问题描述】:

我正在使用 Spring 3 和 Hibernate 3.6 开发 Web 应用程序。目前,我试图了解使用 Spring 和 Hibernate 进行缓存是如何工作的。我找到了一些关于使用 Hibernate 进行缓存的资源和一些关于 Spring 的资源,我现在尝试将我的信息整合在一起。我仍然对这两个框架有一些疑问,如果有人能回答这些问题或告诉我这里列出的事实是否正确,我会很高兴。

大多数时候,简短的回答(是/否)就足够了。我认为这个列表对其他人也很有用,他们想了解使用 spring 和 hibernate 进行缓存是如何工作的。

General

1) Hibernate 支持以下缓存:一级缓存、二级缓存、查询缓存

2) Spring 本身支持以下缓存可能性:只是方法缓存

1st Level Cache

3) 一级缓存是每个 Hibernate 应用程序的一部分。

4) 为每个休眠会话创建一级缓存。

5) 一级缓存中保存了什么?对象还是仅仅是它们的属性值?查询及其结果?

2nd Level Cache

6) 我发现:二级缓存在每个应用程序中使用一次。那不是假的吗?不是每个SessionFactory 使用一次吗?并且:多个 sessionfactorys = 可能有多个二级缓存?

7) 二级缓存中保存的内容:在我看来只是属于一条记录的值,而不是对象本身。

8)在二级缓存中存储一​​条记录的值时,是否也可以使用它存储相关值(来自通过外键连接的对象)?

9)在二级缓存中更新一个对象的值时,缓存中与之相连的对象的值是否也可以更新?

10) 当对象的值发生变化时,如何更新二级缓存?冲洗?我可以只更新部分缓存还是必须更新整个缓存?

11) 二级缓存在哪里有意义,在哪里没有意义?

12)缓存模式:每种缓存模式是否提供不同的缓存策略?例如,对于“只读”缓存模式,不需要同步数据库和缓存吗?其他缓存模式是否提供同步?我认为必须由开发者自己完成同步?

Query Cache

13) 查询缓存和二级缓存有什么区别?在我看来:在查询缓存中,结果集被保存,但没有保存它们的值,只是保存了它们的 id。当再次使用查询,结果集仍然“正确”时,从二级缓存中查询属于ids的值

14) 对于查询缓存,必须使用二级缓存吗?

15) 查询缓存在哪里有意义,在哪里没有意义?

Spring

16) Spring 是否提供了比方法缓存更多的缓存可能性?

17) 方法缓存未链接到休眠缓存

18) 但是:对于方法缓存,第二级是必要的,例如 Ehcache(也可以被休眠使用)

19)可以在没有数据库查询的情况下使用方法缓存吗?

Getting mixed up

20) 如果将ehcache 用于hibernate 作为二级缓存,将Ehcache 用于spring 用于方法缓存,我可以使用相同的Ehcache 实例吗?有没有可能搞混?

21) 使用一级缓存和二级缓存时,会不会混淆?查询数据库时,结果是从哪里来的,一级缓存还是二级缓存?一级缓存可以和二级缓存一起使用吗?

22) 还有什么可以通过使用我提到的缓存来混淆的吗? :-)

感谢您的回答,无论是什么问题! :-)

【问题讨论】:

【参考方案1】:

Hibernate 支持以下缓存:一级缓存、二级缓存、查询缓存

是的。

Spring 本身支持以下缓存可能性:只是方法缓存

Spring 3.1 引入了基于方法注释的新缓存抽象,是的。

一级缓存是每个 Hibernate 应用程序的一部分。

是的。

为每个休眠会话创建第一级缓存。

是的,尽管您可以随时手动清除它。

一级缓存中保存了什么?对象还是仅仅是它们的属性值?查询及其结果?

它是一个会话生命周期内获取的所有对象的映射,如果你第二次按 id 加载同一个对象,它将从 L1 加载。

我发现:二级缓存在每个应用程序中使用一次。那不是假的吗?它不是每个会话工厂使用一次吗?并且:多个 sessionfactorys = 可能有多个二级缓存?

你是对的,通常每个应用程序(数据库)只有一个会话工厂,因此是快捷方式。

二级缓存中保存的内容:在我看来只是属于一条记录的值,而不是对象本身。

与 L1 中的内容相同,但它们的寿命更长。 L2 通常由一些工业级缓存支持,而 L1 只是一个映射(它甚至不必是线程安全的)。它存储完整的实体,包括延迟加载的关系。

在二级缓存中存储一​​条记录的值时,是否也可以存储相关值(来自通过外键连接的对象)?

您无需手动管理 L2,它会自动发生。

当更新二级缓存中一个对象的值时,是否也可以更新缓存中与之相连的对象的值?

见上文。

当对象的值发生变化时,如何更新二级缓存?冲洗?我可以只更新部分缓存还是必须更新整个缓存?

见上文 - Hibernate 会为您解决这个问题。你永远不会直接与 L2 交互。

二级缓存在哪里有意义,在哪里没有意义?

测量。在通过主键读取大量数据且读写因子非常高的应用程序中,L2 对您的性能影响很大。

缓存模式:每种缓存模式是否提供不同的缓存策略?例如,对于“只读”缓存模式,不需要同步数据库和缓存吗?其他缓存模式是否提供同步?我认为必须由开发者自己完成同步?

缓存模式帮助 Hibernate 选择最佳的缓存和失效策略。例如,如果缓存是只读的,Hibernate 不会费心使它失效(或者它不会经常这样做)。但是只读缓存(只读实体)当然会禁止任何更新。

查询缓存和二级缓存有什么区别?在我看来:在查询缓存中,结果集被保存,但没有保存它们的值,只是保存了它们的 id。当再次使用查询,结果集仍然“正确”时,从二级缓存中查询属于ids的值。

没错,但这是一个非常广泛的话题。尤其是结果集仍然是“正确的”部分。

对于查询缓存,必须使用二级缓存吗?

是的,没有二级缓存,查询缓存没有意义,会大大拖慢应用程序的速度。

查询缓存在哪里有意义,在哪里没有意义?

难题,通常是当您多次执行相同的查询并且查询参数的范围很低时(对于每组查询参数,都会创建新的查询缓存,所有记录的 id 都是结果)。

Spring 是否提供了比方法缓存更多的缓存可能性?

不,Spring 或多或少只是您自己代码的粘合剂。

方法缓存未链接到休眠缓存。

Spring 没有链接到 Hibernate,所以...

但是:对于方法缓存来说,第二级是必要的,比如 ehcache(也可以被 hibernate 使用)

L2 是休眠的概念。如果你想缓存方法,你需要一些底层缓存。让它成为 EhCache,没关系。当然它必须是线程安全的。

可以在没有数据库查询的情况下使用方法缓存吗?

Spring 与 Hibernate 无关。您可以缓存与数据库无关的计算。

如果将 ehcache 用于 hibernate 作为二级缓存,将 ehcache 用于 spring 用于方法缓存,我可以使用相同的 ehcache-instance 吗?有没有可能搞混?

您可以使用与 Hibernate 相同的 CacheManager 和缓存配置来简化部署。只要缓存名称不重叠,它们就是完全独立的,即使在同一个管理器中工作也是如此。

当使用一级缓存和二级缓存时,它们会混淆吗?查询数据库时,结果是从哪里来的,一级缓存还是二级缓存?一级缓存可以和二级缓存一起使用吗?

只要某些抽象不泄漏,它们就可以工作:-)。当您通过主键查询时,首先检查 L1(它更快),然后检查 L2。

还有什么可以通过使用我提到的缓存来混淆的吗? :-)

见上文,抽象往往会泄漏。但是当您更改数据库并且 Hibernate 不知道它时,就会出现最严重的问题。没有正确复制的集群也会让你头疼。最大的问题 - 通常不正确的缓存实际上会降低应用程序的速度(查询缓存在这里是最危险的)。

【讨论】:

你是一位善良的老师 :)【参考方案2】:

关于 Spring 和二级缓存,有一些很酷的开源项目可以帮助 Spring 使用 2L 缓存:

例如: http://code.google.com/p/ehcache-spring-annotations/

我们在生产环境中使用它,它让我们的生活更轻松。

【讨论】:

我知道 - 这就是我所说的“方法缓存”。一样的

以上是关于使用 Hibernate + Spring 进行缓存 - 一些问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 Hibernate 和 Spring 进行批量插入

使用 Spring JPA / Hibernate 进行条件插入

使用 Spring/Hibernate 进行密码加密 - Jasypt 还是其他? [关闭]

使用 H2 DB 进行 Spring/Hibernate 集成测试

如何使用 Spring + Hibernate 对实体进行自定义验证以进行多租户设置

使用 Spring 3 和 Hibernate 3 进行身份验证(基于注释)