当前位置: 首页 > 面试题库 >

休眠查询缓存-对于不在第二级缓存中的对象-有风险吗?有用?不好的做法?

松烨烨
2023-03-14
问题内容

前提:

这些是我的假设,根据我的阅读,经验和理解,它们可能是错误的,如果是错误的,请发表评论,然后我将编辑问题。

  • 查询缓存通常与第二级缓存一起很好
  • 查询缓存缓存查询+参数的标识符结果
  • 如果数据库已更改,并且没有反映到缓存中,则查询缓存存在风险

题:

我有一个不在二级缓存中的对象。由于某些不良的编程或其他约束,导致在同一hibernate会话中多次调用加载对象的代码。检索使用HQL查找查询,例如

 hibernateTemplate.find("from Foo f where f.bar > ?", bar);

在添加查询缓存之前,如果以上代码在同一Hibernate会话中被调用了N次,则数据库有N次点击

然后我想看看如果添加查询缓存会发生什么:

 Query query = session.createQuery("from Foo f where f.bar > ?");
 query.setCacheable(true);
 query.setParameter(bar);
 query.list();

当我添加查询缓存时,我注意到在同一会话期间,hibernate不再N次访问数据库,每个会话仅一次。

  1. 因此,我的第一个假设是,Hibernate首先在会话缓存中搜索,然后在第二级缓存中搜索。这个假设正确吗?
  2. 我还假设,如果Foo不在数据库中的第二级缓存中的对象()被更改,则跨会话范围的查询缓存将返回错误的标识符,从而返回错误的对象。那是对的吗?
  3. 那么可以肯定地说,即使对于非2L缓存的对象,也对包含不可变信息的查询使用查询缓存是一种好习惯吗?(例如,查询中的where子句包含始终返回相同结果的条件,例如,一旦创建后ser_num和id对不变,则“选择select p.ser_num where p.id =?”)

顺便说一句,在相关问题中,声称查询缓存在会话缓存范围上不起作用。我是否会误解该声明,还是其他?


问题答案:

查询缓存是第二级缓存的一种特殊类型。您所说的二级缓存我更喜欢称之为“对象缓存”。

关于您的假设的评论:

  • 查询缓存通常与第二级缓存(也称为对象缓存)一起很好。

查询缓存仅将查询的原始结果作为主键保存,在hibernate状态下为id。它不容纳实际的水合物体。这是有道理的,因为当您使用jdbc执行查询时,实际上只在迭代ResultSet时才给您水合(填充)的对象。该陈述不一定正确。如果查询非常复杂,因此运行时间很长,那么使用查询缓存可以节省时间。通过使用查询缓存,您将不会节省从数据库加载对象所花费的时间。

  • 如果数据库已更改,并且没有反映到缓存中,则查询缓存存在风险

这是正确的,但查询缓存并不是唯一的,对于您所说的第二级缓存(通常称为对象缓存)也是如此。

因此,我的第一个假设是,Hibernate首先在会话缓存中搜索,然后在第二级缓存中搜索。 这个假设正确吗?

是的,当加载对象时,这就是行为。

我还假设,如果不在数据库中的二级缓存中的对象(Foo)已在数据库中更改,则跨会话范围的查询缓存将返回错误的标识符,从而返回错误的对象。 那是对的吗?

是的,对象缓存和查询缓存都将受到影响。仅当更改数据库而不通过hibernate时才需要考虑这一点。您可以通过设置查询缓存的超时来减轻这种影响。

那么可以肯定地说,即使对于非2L缓存的对象,也对包含不可变信息的查询使用查询缓存是一种好习惯吗?(例如,查询中的where子句包含始终返回相同结果的条件,例如,一旦创建后ser_num和id对不变,则“选择select
p.ser_num where p.id =?”)

对于这类对象,没有理由不同时使用对象缓存和查询缓存。

是的,查询缓存不适用于会话级别(也称为级别1缓存)。因此,当您再次执行查询时,它再次命中数据库的原因。它不会将查询的结果(标识集)放入会话缓存中。



 类似资料:
  • 问题内容: 一级缓存与hibernate中的查询缓存是否不同?我看过有关第一级和查询缓存的文章,所以我很困惑。 问题答案: 默认情况下,第一级缓存处于启用状态,并且基于每个会话。默认情况下,查询缓存未启用,它在多个会话之间共享,应始终与二级缓存一起使用。 要启用查询缓存,应使用以下属性:

  • 问题内容: 我正在使用Spring + JPA + Hibernate。我正在尝试启用Hibernate的二级缓存。在我的春天,我有: 运行时出现错误: 所以有人抱怨我没有启用二级缓存。我试图通过添加到我的启用它: 但是仍然没有喜悦。我还尝试将其添加到ehcache.xml中: 但这仍然行不通。将更改为也无济于事: 我的实体类被注释为使用缓存 那么,如何启用二级缓存? 编辑: 这是在bean下:

  • 通过CDN(HTTP-)为不可缓存的资源提供服务有什么好处吗? (我的用例:我正在提供一个静态的单页应用程序,我想改善它的加载时间,但是我不想让被缓存,因为我希望每个新版本都能立即反映出来。具体来说,这个静态网站托管在AWS S3上,CDN是AWS云前线。) 我假设CDN的大部分性能优势都是通过缓存实现的,但我可以想象由于私有网络基础设施带来的其他优势。由于我对网络一无所知,这听起来可能是个愚蠢的

  • 当你使用本地(在内存中)缓存时,服务器可以缓存一些信息并快速地检索它,但是其他服务器不能访问这个缓存数据,他们需要到数据库中查询同样的信息。 如果你喜欢使用分布式缓存让其他服务器访问缓存的数据,由于它有一些序列化/反序列化和网络延迟开销,则需要注意:在某些情况下,它可能会降低性能。 缓存需要处理的另一个问题:缓存失效。 There are only two hard things in Compu

  • 我想澄清一些关于hibernate二级缓存的问题。需要澄清的一点是,HQL查询是否总是会击中数据库(至少对于获取id)。 假设我们有实体 地址的数据库表有一个对客户(id)的外键引用,以支持一对多关系。 作为前提条件,我已将hibernate的2级缓存启用为EHcache。只有实体和关联被设置为可缓存。未启用查询缓存。 我知道如果我使用这个会话。get()或会话。load()多次,只有第一次调用才

  • 我正在将spring 4.1与ehcache一起使用。我可以用整数键缓存字符串值,但每当我尝试缓存对象时,它都会失败,不会出现任何错误。我保存在缓存中的模型(POJO)确实实现了hashcode、equals和tostring函数。 ehcache配置如下 Spring配置如下所示 我要缓存的类和方法 如果我将getPerson方法的返回值从Party对象替换为String,它就会工作。有什么想法