在扩展 CrudRepository 的接口中缓存可分页对象(结果)
Posted
技术标签:
【中文标题】在扩展 CrudRepository 的接口中缓存可分页对象(结果)【英文标题】:Caching Pageable objects (results) in interface that extends CrudRepository 【发布时间】:2018-04-10 21:52:40 【问题描述】:我正在使用spring boot和maven创建一个存储库,存储搜索文章的结果,我通过pagination
显示这些结果,界面如下:
public interface HelpArticleSearchRepository extends CrudRepository<HelpArticleSearchResults, Integer>
Page<HelpArticleSearchResults> findAll(Pageable pageable);
我的问题是:我从 REST API 查询中获取搜索文章的结果,但响应速度很慢。
所以,我在网上搜索了缓存解决方案,但我发现的解决方案似乎只适用于methods
,它返回用于将数据存储到存储库中的相同类实例。喜欢:
我希望得到一个适用于 pagination
的解决方案,但我还是 Spring Boot 新手,所以这是一个巨大的挑战。
请为我指明正确的方向,我很乐意提供任何其他信息。
【问题讨论】:
【参考方案1】:如果我不受字符数的限制,我不会将其发布为 aswer,因为它不是您问题的实际答案。相反,它将质疑您的需求,正如您所说的那样,您是该领域的新手。看。在开发的早期阶段缓存的典型方法是:不缓存。这可能是你错的地方。如果你从一开始就需要缓存,我认为这并不好,除非你有一些特殊情况。
接下来。你的用例是什么?您使用缓存,因为有人经常调用 findAll?这是非常奇怪的设计,因为假设您的数据库有数百万条记录。如果您以这种方式进行缓存,您只需将整个数据库(理论上)移动到内存中。如果“所有数据”没有那么大,那么 findAll 不会花费那么多时间,也不需要缓存。但是如果它们很多,那么可能没有人每次都想要它们,即使他们这样做并且您以某种方式使用缓存,您的整个(500M 行表)是否适合内存?因此,正如其他人所说,您需要分页。如果发现这不太可能,其余客户端将频繁调用 findAll,对于包含大量记录的数据库表,我根本不会公开此端点。
好的,所以您有分页或相对较小的表格。你想要缓存这些记录。如果你使用 hibernate,也许你想使用 L2 缓存,它会为你正确地缓存持久化上下文(实际上缓存并不那么容易)。
总结:如果可能,请更改您的设计以不使用 findAll。如果不可能,请使用现有解决方案,例如 L2 缓存。仅当您确实没有其他选择或您确实知道自己在做什么时,才使用您自己的 db 结果缓存实现。
【讨论】:
不知道我们是否可以在这里分享链接,但让我们试试:baeldung.com/hibernate-second-level-cache【参考方案2】:您可以缓存 findAll 结果 [而不是缓存分页结果] 并从服务层处理分页部分。
详细说明: 第 1 步:对于第一个请求 - 我们将缓存 findAll 结果,即 List findAll(); 第2步:现在将在serviceLayer处理分页并发布结果 第 3 步:从下一个请求开始,您将引用缓存的结果并从缓存中发送所需的记录集
根据您的应用程序正在处理的业务类型,可以配置缓存生命周期,以便定期刷新缓存。还记得设置缓存的最大大小。
【讨论】:
【参考方案3】:缓存和分页是不同的问题。假设您有一些用作主要数据源的 REST API,并且速度很慢。所以你想创建一些反应更快的缓存(还没有分页问题)。当然,随着您的缓存而来的是所有相关问题,例如过时的数据、“命中和未命中”等等。假设您解决了这些问题,现在您有一个分层数据源,其中包含一个主要的慢速数据源和缓存。现在在您的 findAll
方法中,您依赖于 Spring boot 为您提供的分页功能(无论您使用什么数据源)。顺便说一句,您的存储库应该扩展 PagingAndSortingRepository
,它扩展了 CrudRepository
。见参考here
【讨论】:
以上是关于在扩展 CrudRepository 的接口中缓存可分页对象(结果)的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot JPA CrudRepository 选择性更新 - 只有一些属性
使用 Spring Data JDBC 和 CrudRepository 接口的多个数据源