Hibernate、二级缓存和查询缓存

Hibernate、二级缓存和查询缓存,hibernate,second-level-cache,query-cache,Hibernate,Second Level Cache,Query Cache,我正在使用Hibernate和Ehcache。不过,我认为这不重要。。 当一个用户登录时,我通过他的电子邮件识别他,并且我使用他的电子邮件进行所有后续呼叫。 现在,由于电子邮件不是我的hibernate id,而是我用@id注释的id,所以我必须用查询加载它,并将其存储在查询缓存中。但是,当用户注销时,我无法明确地将其从缓存中驱逐,因为他存储在一个区域内,该区域与自那时以来已登录的其他用户共享 我的问题是:我是否可以将用户加载到二级缓存中,从而使逐出更容易,而不必使用session.getuse

我正在使用Hibernate和Ehcache。不过,我认为这不重要。。 当一个用户登录时,我通过他的电子邮件识别他,并且我使用他的电子邮件进行所有后续呼叫。 现在,由于电子邮件不是我的hibernate id,而是我用@id注释的id,所以我必须用查询加载它,并将其存储在查询缓存中。但是,当用户注销时,我无法明确地将其从缓存中驱逐,因为他存储在一个区域内,该区域与自那时以来已登录的其他用户共享

我的问题是:我是否可以将用户加载到二级缓存中,从而使逐出更容易,而不必使用session.getuser方法再次访问数据库? 这里还有一点,如果用户更新了查询缓存,则该用户的查询缓存将出错。我希望在更新用户时更新它

为什么要将用户从缓存中逐出?适当地配置缓存,当它不再使用时,它会在一段时间后将其从缓存中删除

如果您通过hibernate更新用户,那么二级缓存应该会看到并处理它


在我看来,您似乎想了解Hibernate中的缓存:

第一个问题:为什么要在用户注销时将其从查询缓存中删除?我无法想象为什么您的体系结构需要这样。缓存应该是透明的,当不再需要或不适合缓存时,EhCache可以轻松删除用户

如果用户已更新,则此用户的Querycache将出错

不,不会的,至少如果更新是通过Hibernate进行的。你知道查询缓存是如何工作的吗?在您的情况下,它存储电子邮件->用户id映射。通过电子邮件查询时,Hibernate将首先查找与此电子邮件关联的用户id,然后按id查找用户。如果它存在于二级缓存中,则从那里加载。否则,Hibernate会透明地按id加载用户。不过,它仍然比通过电子邮件进行查询要好

也就是说,如果更新用户,Hibernate将自动更新/退出二级缓存,并更新涉及用户的所有查询的查询缓存。它只是工作

我希望在更新用户时更新它

你什么意思?您将遇到的唯一过时数据是存储在一级缓存中的用户实例,二级缓存和查询缓存将无缝更新


另请参见:

您使它变得比必要的更困难。使用查询缓存避免每次使用相同参数执行查询时命中数据库。如果用户注销,带有这些特定参数的查询随后将不会执行太多,缓存最终将根据其逐出策略LRU、超时等从缓存中逐出此特定查询。。缓存应该是透明的,您不必逐出任何内容

如果您使用ID来引用用户,而不是使用他的电子邮件地址,则可以完全避免此用例的查询缓存。ID用于:唯一地引用实体,并且能够使用session.get和session.load加载用户。使用电子邮件登录是可以的。登录后,应用程序应该使用他的ID来引用用户,而不是他的电子邮件


关于最后一点:如果您更新用户,Hibernate将自动使缓存的结果无效。即使没有,查询缓存也只存储返回的实体的ID。实体的状态是从实体缓存加载的,当实体更新时,实体缓存将失效或更新。

实际上,我不太关心注销时的逐出,而更关心的是二级缓存没有看到用户的更新。让我正确地理解一下,如果我启用了二级缓存,那么hibernate将自动将我通过电子邮件检索到的实体存储在二级缓存中?不。您还必须为用户实体启用缓存。但是,如果您更新用户,则“通过电子邮件选择用户”查询的缓存结果将自动退出。如果我更新一个用户,整个用户缓存就会被逐出?听起来不太好,我想是这样的。如果更新一个用户,Hibernate将无法再确保涉及用户的任何查询的结果都是正确的。例如,您有一个查询,返回给定时间范围内创建的所有用户。当更新单个用户或添加新用户时,Hibernate不够聪明,无法猜测更新后哪些结果不再相关。这些都在UpdateTimestampsCache中跟踪。