SpringBoot3+SpringDataJPA+Ehcache3做分页查询的缓存优化

前言:关于集成Ehcache3的集成,需要了解的可以出门左转:
https://blog.csdn.net/qq_42755868/article/details/143870473 这里
本文也是基于这个前置条件写的。大佬可以忽略哈。

基于上文:我们在做分页查询的时候,可以将分页数据进行缓存。比如以下low方案
该方案:诸如此类比较简单易上手,但是对于缓存数据的维护来说,有点小麻烦,另外过大的key也可能会一定程度的影响缓存性能
所以:看方案二,我这里制作到了方案二,还有更好的(恕鄙人无能)。

@Service
@Transactional
public class UsersServiceImple implements IUsersService {//JPA 简化sql,用于替换usermapper@Autowiredprivate UsersRepository usersRepository;@Cacheable(value="tests2"/*注意这个cache需要在ehcache里配一下*/,key="getMethodName().concat('_').concat(T(String)."+"valueOf(#pageable.pageNumber)"+".concat('::').concat(#pageable.pageSize))")@Overridepublic Page<Users> findUserByPage(Pageable pageable) {return this.usersRepository.findAll(pageable);}
}

方案二:在数据库IO层面,可能会碰到大表数据查询较慢,这里如果只分页查询id,发挥主键索引的效果,性能应该可以得到提升
基于这一点我想到的是:还有优化思考空间~(比如:事务相关)

	 1. 分页查询数据库的ID列表2. 根据ID列表去获取缓存中通过(ID,Bean)形式存储的bean实例,2.1 (注意这个bean实例的维护需要做的全面一点,比如CRUD相关操作,我这里只演示分页查询的啦)3. 如果全命中缓存中的记录,则封装返回查询的结果,这里如果使用的缓存支持批量操作,会更好,如redis的mget之类,结合Pipleline会更好的发挥缓存的性能。4. 如果部分命中,或者0命中。暂存命中部分的记录,然后整理出未命中的id,批量查询出数据库的记录。将该记录一并合入到暂存的记录中。同时,将未命中的结果更新到缓存中。5. 返回结果。搞掂!!!
@Repository
public interface UsersRepository extends JpaRepository<Users,Integer> {@Query(nativeQuery = true, value = "select id from users")Page<Integer> findAllIds( Pageable pageable);List<Users> findByIdIn(List<Integer> ids);
}
@Service
@Transactional
public class UsersServiceImple implements IUsersService {@AutowiredCacheManager cacheManager;//JPA 简化sql,用于替换usermapper@Autowiredprivate UsersRepository usersRepository;//采用,分页查询id,然后通过id批量获取存入到缓存的实例@Overridepublic Page<Users> findUserByPage2(Pageable pageable) {//return this.usersRepository.findAll(pageable);//原始数据库策略//做缓存分页查询策略Cache cache = cacheManager.getCache("users");Page<Users> usersPage = null;if(cache==null){//0、缓存死亡(无缓存),从数据库中去获取,后续查询数据由其他接口更新进缓存usersPage = this.usersRepository.findAll(pageable);}else{//1、获取分页查询的id虚拟集,充分发挥库的主键索引优势Page<Integer> idListPageDB = this.usersRepository.findAllIds(pageable);List<Users> usersCache = getPageEleFromCache(idListPageDB, cache);//2、剥离缓存中没有命中的id列表List<Integer> idListDB = idListPageDB.getContent().stream().collect(Collectors.toList());usersCache.forEach(users -> idListDB.removeIf(ele->ele.compareTo(users.getId())==0));//3、当存在缓存中没有命中的id列表,则从数据库中去获取数据记录if(!CollectionUtils.isEmpty(idListDB)){//3.1 获取数据库中的未命中记录System.out.println("缓存中存在没有数据情况,需要到数据空去获取!!!!!");List<Users> usersDB = this.usersRepository.findByIdIn(idListDB);usersCache.addAll(usersDB);//3.2 尝试将未在缓存中查到的数据重新放回缓存中usersDB.forEach(users ->  cache.put(users.getId(),users));}else{System.out.println("从缓存中获取到内容");}//4、将最终的记录封装到分页类中usersPage = new PageImpl<>(usersCache,pageable,idListPageDB.getTotalElements());}return usersPage;}/*** 根据Id列表,获取缓存中的存放的目标元素* @param idListPageDB* @param cache* @return*/private static List<Users> getPageEleFromCache(Page<Integer> idListPageDB, Cache cache) {List<Users> usersListCache = idListPageDB.stream().map(id -> cache.get(id)!=null?(Users)(cache.get(id).get()):null).filter(ele->ele!=null).collect(Collectors.toList());return usersListCache;}
}

附:部分代码的说明
在这里插入图片描述
在这里插入图片描述
测试:
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/887081.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VS2022进行Libigl库编译

目录 一 编译OK 二 编译难点 2.1 cmake问题 2.2 文件编码问题 三 调用链接 一 编译OK 二 编译难点 2.1 cmake问题 vs2022直接多次cmake生成即可。 2.2 文件编码问题 格式保存为GB2312. 三 调用链接 https://github.com/libigl/libigl-example-project

风尚云网前端学习:一个简易前端新手友好的HTML5页面布局与样式设计

风尚云网前端学习&#xff1a;一个简易前端新手友好的HTML5页面布局与样式设计 简介 在前端开发的世界里&#xff0c;HTML5和CSS3是构建现代网页的基石。本文将通过一个简单的HTML5页面模板&#xff0c;展示如何使用HTML5的结构化元素和CSS3的样式特性&#xff0c;来创建一个…

返回流类型接口的错误信息处理

返回流类型接口的错误信息处理 前言axios拦截器src/utils/request.ts对应接口 前言 返回流类型接口需要在响应成功回调里拦截&#xff0c;且该接口的status始终是200&#xff0c;尽管后端返回的code可能是非2xx&#xff0c;因此返回流类型的接口&#xff0c;其错误信息需要单独…

Python入门(13)--并发编程

Python并发编程&#xff1a;从入门到实践 &#x1f680; 1. 多线程编程基础 &#x1f9f5; 多线程是实现并发的重要方式&#xff0c;Python提供了threading模块来支持多线程编程。 1.1 基本线程操作 import threading import time from typing import List, Callableclass …

工程师 - 智能家居方案介绍

1. 智能家居硬件方案概述 智能家居硬件方案是实现家庭自动化的重要组件&#xff0c;通过集成各种设备来提升生活的便利性、安全性和效率。这些方案通常结合了物联网技术&#xff0c;为用户提供智能化、自动化的生活体验。硬件方案的选择直接影响到智能家居系统的性能、兼容性、…

SMMU软件指南操作之翻译过程概述

安全之安全(security)博客目录导读 下图展示了每个传入事务&#xff08;transaction&#xff09;所经过的简化过程。本节描述了顶层翻译过程。 一个传入事务遵循以下步骤&#xff1a; 1. 如果 SMMU 被全局禁用&#xff0c;事务将直接通过 SMMU 而不进行任何地址改变。全局属性…

特征交叉-MaskNet文章总结代码实现

MaskNet 这个模型是微博21年提出的&#xff0c;23年twitter(X)开源的推荐系统排序模块使用的backbone结构。 核心思想是认为DNN为主的特征交叉是addictive&#xff0c;交叉效率不高&#xff1b;所以设计了一种multiplicatvie的特征交叉 如何设计muliplicative特征交叉呢&#x…

QT 实现仿制 网络调试器(未实现连接唯一性) QT5.12.3环境 C++实现

网络调试助手&#xff1a; 提前准备&#xff1a;在编写代码前&#xff0c;要在.pro工程文件中&#xff0c;添加network模块。 服务端&#xff1a; 代码&#xff1a; widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QtWidgets> #inclu…

Vscode写markdown快速插入python代码

如图当我按下快捷键CRTLSHIFTK 自动出现python代码片段 配置方法shortcuts’ 打开这个json文件 输入 {"key": "ctrlshiftk","command": "editor.action.insertSnippet","when": "editorTextFocus","args&…

【案例】泛微.齐业成助力北京中远大昌汽车实现数电票全流程管理

中远大昌统一发票共享平台上线三个多月以来&#xff0c;实现&#xff1a; 5000份 60000元 发票开具 成本节约 客户简介及需求分析 北京中远大昌汽车服务有限公司&#xff08;以下简称“中远大昌”&#xff09;成立于2002年&#xff0c;是中远海运集团所属香远&#xff08;北…

使用docker快速部署Nginx、Redis、MySQL、Tomcat以及制作镜像

文章目录 应用快速部署NginxRedisMySQLTomcat 制作镜像镜像原理基于已有容器创建使用 Dockerfile 创建镜像指令说明构建应用创建 Dockerfile 文件创建镜像 应用快速部署 Nginx docker run -d -p 80:80 nginx使用浏览器访问虚拟机地址 Redis docker pull redis docker run --…

雅思阅读TFNG题型7大解题思路

雅思阅读TFNG题型7大解题思路&#xff0c;全在这了‼️ ⚠️在徘徊在6-6.5的同学有很大的共性就是对题型不够熟悉&#xff0c;我记得我当时卡6.5的时候我有时候分不清NG和F&#xff0c;有时候又分不清NG 和True&#xff0c;也不知道他有哪几种考我的方法&#xff0c;脑子里没有…

家政服务系统开发,智慧家政,便捷生活

近年来&#xff0c;大众对家政服务的需求不断增加&#xff0c;家政服务种类也逐渐多样化&#xff0c;涵盖了日常生活中的各个方面&#xff0c;为大众带来更急优质的服务&#xff0c;进一步提升了家政市场的发展。 在数字化发展的推动下&#xff0c;互联网家政服务的模式应运而…

重生之我在学环境变量

环境变量 基本概念 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数如&#xff1a;我们在编写C/C代码的时候&#xff0c;在链接的时候&#xff0c;从来不知道我们的所链接的动态静态库在哪里&#xff0c;但 是照样可以链接成功&#…

Java基础夯实——2.7 线程上下文切换

线程上下文切换&#xff08;Thread Context Switching&#xff09;是操作系统在多线程环境中&#xff0c;切换CPU从执行一个线程的上下文到另一个线程的上下文的过程。这种切换是实现多线程并发执行的核心机制之一。 1 上下文: 线程的上下文指线程在某一时刻的执行状态,如&am…

AI模型简介

深度学习模型种类繁多&#xff0c;可以根据任务类型和应用场景进行分类。以下是主要模型类型的详细介绍&#xff0c;每种模型包含了其特点、功能、代表性模型&#xff0c;以及常见应用。 1. 分类模型 分类模型是深度学习中最基本也是最广泛应用的模型类型&#xff0c;其目标是…

Failed to start Docker Application Container Engine

说明&#xff1a; 1&#xff09;访问应用业务&#xff0c;读取不到数据&#xff0c;show databases;查看数据库报错 2&#xff09;重启docker服务&#xff0c;服务启动失败&#xff0c;查看日志报错如下图所示 3&#xff09;报错信息&#xff1a;chmod /data/docker: read-only…

SQL 语句执行计划中的连接方式

SQL 语句执行计划中的连接方式 join操作 join操作基本分为3大类&#xff1a;外连接&#xff08;细分为&#xff1a;左连接&#xff08;Left outer join/ left join&#xff09;、右连接&#xff08;right outer join/ right join&#xff09;、全连接&#xff08;full outer …

如何理解Lua 使用虚拟堆栈

虚拟堆栈的基本概念 Lua使用虚拟堆栈来实现Lua和C&#xff08;或其他宿主语言&#xff09;之间的交互。这个虚拟堆栈是一个数据结构&#xff0c;用于存储Lua的值&#xff0c;如数字、字符串、表、函数等。它在Lua状态机&#xff08;lua_State&#xff09;内部维护&#xff0c;为…

FileProvider高版本使用,跨进程传输文件

高版本的android对文件权限的管控抓的很严格,理论上两个应用之间的文件传递现在都应该是用FileProvider去实现,这篇博客来一起了解下它的实现原理。 首先我们要明确一点,FileProvider就是一个ContentProvider,所以需要在AndroidManifest.xml里面对它进行声明: <provideran…