【问题标题】:how to stop default query on id when using @cacheable annotation使用@cacheable注解时如何停止对id的默认查询
【发布时间】:2020-06-07 12:15:25
【问题描述】:

当在具有自定义键(如名称)的存储库上使用 @Cacheable 注释(org.springframework.cache.annotation.Cacheable)时,遇到在每个连续请求上对 id 字段运行额外查询的问题。

请参阅下面的存储库代码:

public interface StatusRepository extends JpaRepository<Status, Integer> {

    @Cacheable(value = "StatusByStatusNameCache" , key="#statusName")
    public Status findByStatusName(String statusName);

}

上面你可以看到缓存是只为状态名称定义的,现在在运行第一个请求后得到以下 Hibernate 控制台,查询状态名称:

Hibernate: select status0_.status_id as status_i1_7_, status0_.status_name as status_n2_7_ from status status0_ where status0_.status_name=?
Hibernate: select event0_.event_id as event_id1_3_, event0_.event_name as event_na2_3_ from events event0_ where event0_.event_name=?

现在再打第二个请求,在带有 id 的控制台中获取休眠查询:

Hibernate: select event_.event_id, event_.event_name as event_na2_3_ from events event_ where event_.event_id=?
Hibernate: select requestcha_.request_channel_id, requestcha_.request_channel_name as request_2_6_ from request_channels requestcha_ where requestcha_.request_channel_id=?
Hibernate: select status_.status_id, status_.status_name as status_n2_7_ from status status_ where status_.status_id=?

我不明白为什么这个额外的查询会因为 status_name 查询被缓存而触发,但是如何在第一次请求后的每个连续调用中停止这个 id 查询。

【问题讨论】:

  • 请从日志中复制信息或类似文本并格式化为代码。它使阅读、搜索和复制变得更加容易。
  • 这是什么Cacheable注解?来自 Spring 的那个还是来自 JPA 的那个?两个查询是否来自同一个会话?
  • @JensSchauder 我已经更新了帖子,即使用弹簧可缓存并包含代码格式的日志。

标签: spring hibernate jpa caching spring-data-jpa


【解决方案1】:

Spring 的 @Cacheable 注释完全独立于 Hibernate/您的 JPA 实现提供的任何缓存。

缓存按名称查询的结果不会阻止按id查询,因为对id查询的缓存将由JPA的一级缓存完成,它不知道也不关心Springs缓存。

这可能是怎么回事:

  1. findbyName

    实体在一级缓存和 Springs 缓存中。

  2. 通过 id 进行的任何访问(例如导航到实体)

    实体从一级缓存中获取。

  3. 会话结束。

    实体已从一级缓存中移除

  4. findByName

    实体由 Springs 缓存提供。请注意,这现在是一个分离的实体。一级缓存中没有任何内容。

  5. 通过 id 访问

    实体是从数据库中加载的,因为它在一级缓存中找不到。

您应该启用Hibernates 2nd level cache 以跨会话缓存实体,以便通过 id 访问。

我还建议不要将 JPA/Hibernate 的缓存与 Spring 缓存结合使用,而是使用 JPA 自己的查询缓存来缓存 findByName。请参阅 Spring JPA Hibernate query cache doesn't work 了解如何使其与 Spring Data JPA 一起使用。

也可以看看Vlad Mihalcea about interaction of query cache and 2nd level cache的这篇文章。

注意Oliver Drotbohm seems to have a different opinion

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-19
    • 1970-01-01
    • 1970-01-01
    • 2018-07-03
    • 1970-01-01
    • 1970-01-01
    • 2014-02-20
    • 2018-04-18
    相关资源
    最近更新 更多