我正在使用Hibernate和Ehcache(不要认为这很重要,所以)
当用户登录时,我通过他的电子邮件识别他,并且我将他的电子邮件用于所有后续呼叫。
现在,由于电子邮件不是我的“hibernate id”(我用@Id
注释的那个),我不得不用查询加载它,因此将它存储在查询缓存中。但是,当用户注销时,我无法将其从缓存中明确地逐出,因为他存储在与其他已登录的用户共享的区域内。
我的问题是:我是否可以将用户加载到二级缓存中(从而使驱逐变得更容易)而无需使用session().get(user)
方法再次访问数据库?
这里还有另一点,如果用户被更新,查询缓存将对该用户而言是错误的。我希望在更新用户时更新它
答案 0 :(得分:0)
为什么要从缓存中逐出用户?适当地配置缓存,一段时间后它将被缓存从缓存中删除。
如果您通过休眠更新用户,那么二级缓存应该会看到并处理它。
听起来我想要阅读Hibernate中的缓存:http://www.javalobby.org/java/forums/t48846.html
答案 1 :(得分:0)
第一个问题:为什么要在用户注销时从查询缓存中删除用户?我无法想象为什么你的架构需要这样。缓存应该是透明的,EhCache可以在不再需要或不适合缓存时轻松删除用户。
不,它不会,至少如果更新是通过Hibernate。你知道查询缓存是如何工作的吗?在您的情况下,它存储电子邮件 - > 用户ID 映射。当通过电子邮件查询时,Hibernate将首先找到与此电子邮件关联的用户ID ,然后按ID查找用户。如果它存在于二级缓存中,则从那里加载。否则,Hibernate通过id透明地加载用户。它仍然比通过电子邮件查询更好。如果用户更新,则此用户的Querycache将出错
如果您更新用户,Hibernate将自动更新/逐出L2缓存并更新涉及用户的所有查询的查询缓存。它只是有效。
你是什么意思?您将遇到的唯一陈旧数据是存储在L1缓存中的用户实例,L2和查询缓存可以无缝更新。我希望在更新用户时更新
答案 2 :(得分:0)
你让它变得更加困难。每次使用相同的参数执行查询时,请使用查询缓存来避免命中数据库。如果用户注销,具有这些特定参数的查询将不会在之后执行很多,并且缓存最终将基于其驱逐策略(LRU,超时等)从缓存中驱逐该特定查询。缓存应该是透明的,你不应该驱逐任何东西。
如果您使用ID引用用户而不是使用他的电子邮件地址,则可以完全避免此用例的查询缓存。 ID用于:唯一引用实体,并且能够使用session.get和session.load来加载用户。使用电子邮件登录很好。登录后,应用程序应该使用他的ID来引用用户,而不是他的电子邮件。
关于最后一点:如果更新用户,Hibernate将自动使缓存的结果无效。即使它没有,查询缓存也只存储返回的实体的ID。实体的状态从实体缓存加载,实体更新时无效(或更新)。