95、Spring Data Redis 之使用RedisTemplate 实现自定义查询 及 Spring Data Redis 的样本查询
Spring Data Redis 之使用RedisTemplate 实现自定义查询
Book实体类

原本的接口,再继承我们自定义的接口

自定义查询接口----CustomBookDao

实现类:CustomBookDaoImpl
1、自定义添加hash对象的方法

2、自定义查询价格高于某个点的Book对象

测试:自定义添加hash对象的方法

成功添加hash对象到redis数据库

测试:自定义查询价格高于某个点的Book对象

结果:
数据:价格有100, 200 ,300这三个

结果正确,因为自定义的查询,是价格 > , 不是 >= 。

Spring Data Redis 的样本查询
如图:因为bookDao有继承这个 QueryByExampleExecutor 接口,所以可以进行样本查询

样本中只有 name 作为参数来查询

样本中只有 author 作为参数来查询

完整代码
Book
package cn.ljh.app.domain;import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.redis.core.TimeToLive;
import org.springframework.data.redis.core.index.Indexed;import java.util.concurrent.TimeUnit;//通过@RedisHash注解存储实体Book到redis,就是该Book对象将存储为books(key)对应的hash对象(value) ---> key(books) field value
//相当于 @Entity 实体类映射到数据库,这里的RedisHash就是把这个book存到redis中
@RedisHash("books")
@Data
public class Book
{@Idprivate Integer id; //即使这里类型是Integer,可是存到redis后,也会变成String类型//Indexed 指定对普通类型的属性建立索引,索引化后的属性才可用于查询。@Indexedprivate String name;@Indexedprivate String author;private double price;//该注解修饰一个数值类型的属性,用于指定该对象的过期时长。@TimeToLive(unit = TimeUnit.MINUTES)private long ttl;public Book(){}public Book(Integer id, String name, double price, String author){this.id = id;this.name = name;this.price = price;this.author = author;}public Book(Integer id, String name, double price, String author, long ttl){this.id = id;this.name = name;this.price = price;this.author = author;this.ttl = ttl;}
}
BookDao
package cn.ljh.app.dao;import cn.ljh.app.domain.Book;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.QueryByExampleExecutor;import java.util.List;//DAO接口只需继承CrudRepository,Spring Data Redis 就能为DAO组件提供实现类。
//参数1:要操作的实体的类型 参数2:Id类型
//继承这个 QueryByExampleExecutor 接口,才可以进行样本查询
public interface BookDao extends CrudRepository<Book, Integer>, QueryByExampleExecutor,CustomBookDao
{//方法名关键字查询//根据 name 查询Book对象//Booke实体类中的 name 属性有添加注解 @Indexed,所以可以对这个属性作为key进行查询List<Book> findByName(String name);//根据 author 查询Book对象//这个author在实体类中也有添加 @Indexed 注解List<Book> findByAuthor(String author);}
CustomBookDao
package cn.ljh.app.dao;import cn.ljh.app.domain.Book;import java.util.List;
import java.util.Map;//自定义查询
public interface CustomBookDao
{//自定义添加hash对象的方法void hmset(String key, Map<String,String> value);//自定义查询价格高于某个点的Book对象List<Book> findByPriceGt(double startPrice);}
CustomBookDaoImpl
package cn.ljh.app.dao.impl;import cn.ljh.app.dao.CustomBookDao;
import cn.ljh.app.domain.Book;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.StringRedisTemplate;import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;//自定义查询接口实现类
public class CustomBookDaoImpl implements CustomBookDao
{//借助于自动配置的 StringRedisTemplate 来实现数据库的访问private final StringRedisTemplate stringRedisTemplate;//有参构造器进行依赖注入public CustomBookDaoImpl(StringRedisTemplate stringRedisTemplate){this.stringRedisTemplate = stringRedisTemplate;}//自定义添加hash对象的方法@Overridepublic void hmset(String key, Map<String, String> value){//调用 HashOperations 的方法来向数据库中存入 Hash 对象//要操作的value的类型是hash对象,就用.opsForHash() 方法stringRedisTemplate.opsForHash().putAll(key, value);}//自定义查询价格高于某个点的Book对象@Overridepublic List<Book> findByPriceGt(double startPrice){//由于 price 没有用注解@Indexed 建立索引,因此不能直接根据price来查询//首先获取全部的Book对象,redis会自动把我们添加的所有Book对象中的id,都存在一个set集合里面,因此先把id从set集合中都拿出来//要操作的value的类型是 set 集合,就用.opsForSet() 方法,此处的 books 就是 Book对象上 @RedisHash("books") 所指定的keySet<String> idSet = this.stringRedisTemplate.opsForSet().members("books");//把这个 HashOperations 先提取出来HashOperations<String, String, String> hashOps = this.stringRedisTemplate.opsForHash();//返回接收Book对象的集合List<Book> bookList = new ArrayList<>();//2、遍历id集合,根据id获取所有的实体对象Bookfor (String id : idSet){//key 为 "books:<id值>" 对应的hash对象,就保存着一个个的持久化对象的全部信息。String objkey = "books:" + id;//3、判断key是否存在,因为key即使过期了,也还记录者,该objkey对应的value还存在,那么说明该实体还存在if (this.stringRedisTemplate.hasKey(objkey)){//获取 "books:"+id 的key所对应的 Hash 对象中的price属性--就是Book对象的price属性double price = Double.parseDouble(hashOps.get(objkey, "price"));//4、判断价格,符合条件的再添加到list集合中if (price > startPrice){bookList.add(new Book(Integer.parseInt(hashOps.get(objkey, "id")),hashOps.get(objkey, "name"),price,hashOps.get(objkey, "author")));}}}return bookList;}
}
BookDaoTest
//=========================================样本查询=========================================@Autowiredprivate BookDao bookDao;//==========================自定义查询================================//自定义添加hash对象的方法@Testpublic void testHmset(){bookDao.hmset("test", Map.of("k1", "value1", "k2", "value2"));}//自定义查询价格高于某个点的Book对象@ParameterizedTest@ValueSource(doubles = {100, 200, 300})public void testFindByPriceGt(double startPrice){List<Book> books = bookDao.findByPriceGt(startPrice);books.forEach(System.out::println);}//=========================================样本查询=========================================//样本中只有 name 作为参数来查询@ParameterizedTest@ValueSource(strings = {"七龙珠", "火影忍者"})public void testFindByExampleOnlyName(String name){//创建一个样本对象Example ex = Example.of(new Book(null, name, 0, null),ExampleMatcher.matching()//忽略样本对象中的所有null值,即null值不作为样本的比较属性.withIgnoreNullValues()//因为查询的参数只有name,所以price不参与比较,用这个方法把这个price忽略掉//因为price的默认值是0,不是null,需要额外用这个方法.withIgnorePaths("price"));//查询所有对象,把样本作为条件参数传进去比较查询Iterable books = bookDao.findAll(ex);books.forEach(System.err::println);}//样本中只有 author 作为参数来查询@ParameterizedTest@ValueSource(strings = "鸟山明")public void testFindByExampleOnlyAuthor(String author){//先创建一个样本Example<Book> bookExample = Example.of(new Book(null, null, 0, author),ExampleMatcher.matching().withIgnoreNullValues().withIgnorePaths("price"));//查询所有对象,把样本作为条件参数传进去比较查询bookDao.findAll(bookExample).forEach(System.err::println);}
application.properties
# 配置连接redis服务器的相关信息
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=123456
# 选择连接redis默认16个数据库中的第11个数据库
spring.redis.database=11
# 连接redis超时的时间--30秒
spring.redis.connect-timeout=30s# 配置连接池的相关信息
# 配置这个连接池最大的连接数量
spring.redis.lettuce.pool.max-active=10
# 配置最大的能有多少个活动的、空闲的连接数量 idle-空闲
spring.redis.jedis.pool.max-idle=10
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.5</version></parent><groupId>cn.ljh</groupId><artifactId>redis_boot</artifactId><version>1.0.0</version><name>redis_boot</name><properties><java.version>11</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- 配置连接池需要的依赖 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><version>2.9.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>相关文章:
95、Spring Data Redis 之使用RedisTemplate 实现自定义查询 及 Spring Data Redis 的样本查询
Spring Data Redis 之使用RedisTemplate 实现自定义查询 Book实体类 原本的接口,再继承我们自定义的接口 自定义查询接口----CustomBookDao 实现类:CustomBookDaoImpl 1、自定义添加hash对象的方法 2、自定义查询价格高于某个点的Book对象 测试&a…...
jdbc(DriverManager+Connection+Statement+ResultSet)+SQL注入+开启预编译+数据连接池
1 JDBC概念 JDBC 就是使用Java连接并操作数据库的一套API 全称:( Java DataBase Connectivity ) Java 数据库连接 2 JDBC优势 可随时替换底层数据库,访问数据库的Java代码基本不变 以后编写操作数据库的代码只需要面向JDBC(接口…...
NoSQL之 Redis命令工具及常用命令
目录 1 Redis 命令工具 1.1 redis-cli 命令行工具 1.2 redis-benchmark 测试工具 2 Redis 数据库常用命令 2.1 set:存放数据,命令格式为 set key value 2.2 get:获取数据,命令格式为 get key 2.3 keys 命令可以取符合规则的…...
多线程(线程互斥)
抢票代码编写 学习了前面有关线程库的操作后,我们就可以模拟抢票的过程 假设我们创建四个线程,分别代表我们的用户 然后设定总票数为1000张,四个线程分别将进行循环抢票操作,其实就是循环对票数进行打印,并进行对应的…...
使用 html2canvas 和 jspdf 将页面转 pdf,同时解决当页面过长时,页面白屏问题
代码如下,直接粘贴复制即可,代码中 jspdf 是全局引入,你可以自己局部引入 别人使用标签的方式来显示 base64,但是当页面过长时,base64 大小过大会导致页面解析异常,显示白屏 import html2canvas from html2…...
【Python 千题 —— 基础篇】今年几岁啦
题目描述 题目描述 介绍自己的年龄。请使用 input 函数读入一个整数,表示自己的年龄,然后程序将自动生成介绍自己年龄的英文语句。 输入描述 输入一个整数,表示自己的年龄。 输出描述 程序将生成一个英文语句,以介绍自己的年…...
git push 失败 shallow update not allowed
问题描述: ~/OK62xx-linux-sdk/OK62xx-linux-kernel$ git push origin master Counting objects: 83919, done. Delta compression using up to 144 threads. Compressing objects: 100% (75697/75697), done. Writing objects: 100% (83919/83919), 232.41 MiB | …...
uniapp 在uni.scss 根据@mixin定义方法 、通过@include全局使用
在官方文档中提及到uni.scss中变量的使用,而我想定义方法,这样写css样式更方便 一、官方文档的介绍 根据官方文档我知道,在这面定义的变量全局都可使用。接下来我要在这里定义方法。 二、在uni.scss文件中定义方法 我在uni.scss文件中定义了…...
C++ 类和对象(一)
1.面向过程和面向对象初步认识 C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。 C是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完 成。 …...
rust函数
一 、函数定义 (一)格式 使用fn关键字 fn是 function 的缩写 1.无返回值的 fn 函数名 ( [paraname: type]... ) {函数体 }参数必须声明参数名称和类型 函数定义时指定的参数叫做 形参。调用时传递给函数的参数叫做 实参。 例子 fn another_function(…...
链表的基本操作
(一)实验类型:设计性 (二)实验目的: 1. 掌握线性表的链式存贮结构及基本操作,深入了解链表的基本特性,以便在实际问题背景下灵活运用它们。 2. 巩固该存贮结构的构造方法࿰…...
Flutter AI五子棋
前言 在上一篇文章中,讲解了如何实现双人在本地对战的五子棋,但是只有一个人的时候就不太好玩,同时博主也没有把五子棋相关的文章写过瘾。那么这篇文章,我们来实现一个功能更加丰富的五子棋吧!在设计五子棋的算法方面&…...
springboot项目中后台文件上传处理
参考地址:http://www.gxcode.top/code 文件上次核心处理代码: @Autowired private FileUpload fileUpload; //获取资源对象:file-upload-prod.properties@ApiOperation(value = "用户头像修改", notes = "用户头像修改", httpMethod =...
【SQL】MySQL中的存储引擎、事务、锁、日志
存储引擎: 数据库管理系统(DBMS)使用数据存储引擎进行创建、查询、更新和删除数据。 MySQL5.5之前默认的存储引擎是MyISAM,5.5及之后版本默认的存储引擎是InnoDB。(my.ini中指定的) MyISAM:不支持事务,不支…...
DRM全解析 —— CRTC详解(2)
接前一篇文章:DRM全解析 —— CRTC详解(1) 本文继续对DRM中CRTC的核心结构struct drm_crtc的成员进行释义。 3. drm_crtc结构释义 (5)struct drm_modeset_lock mutex /*** @mutex:** This provides a read lock for the overall CRTC state (mode, dpms* state, ...) an…...
3d环形图开发(vue3+vite+ts)
开发效果(待完善): 技术支持: Echarts echarts-gl 安装: 注:echarts与echarts-gl版本需对应,可参考官网 pnpm add echarts4.9.0 echarts-gl1.1.2 组件封装: <template><…...
element ui中父子组件共用一个el-dialog弹窗,切换组件页面弹窗进行关闭
在Element UI中,如果多个父子组件共用一个el-dialog弹窗,并且需要在切换组件页面时关闭弹窗,你可以考虑以下方法来实现: 使用Vuex进行状态管理: 在Vuex中创建一个状态来管理弹窗的显示状态(例如࿰…...
基于Keil a51汇编 —— Segments, Modules, and Programs
段、模块和程序 在初始设计阶段,定义程序要执行的任务,然后划分为子程序。以下是与 Ax51 汇编器和 Lx51 链接器/定位器一起使用的子程序类型的简要介绍。 段是代码块或数据存储器。段可以是可重定位的,也可以是绝对的。可重定位段具有名称、…...
基于Java+SpringBoot+Vue民宿管理系统的设计与实现 前后端分离【Java毕业设计·文档报告·代码讲解·安装调试】
🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…...
【Qt】三种方式实现抽奖小游戏
简介 本文章是基本Qt与C实现一个抽奖小游戏,用到的知识点在此前发布的几篇文章。 下面是跳转链接: 【Qt控件之QLabel】用法及技巧链接: https://blog.csdn.net/MrHHHHHH/article/details/133691441?spm1001.2014.3001.5501 【Qt控件之QPus…...
告别手动记录!用CAPL脚本的file系列函数自动生成CANoe测试报告
告别手动记录!用CAPL脚本的file系列函数自动生成CANoe测试报告 在汽车电子测试领域,工程师们每天都要面对海量的测试数据——从总线负载率到错误帧统计,从信号值波动到时间戳记录。传统的手动截图、复制粘贴方式不仅效率低下,还容…...
3步打造你的专属AI角色扮演世界:SillyTavern终极指南
3步打造你的专属AI角色扮演世界:SillyTavern终极指南 【免费下载链接】SillyTavern LLM Frontend for Power Users. 项目地址: https://gitcode.com/GitHub_Trending/si/SillyTavern 你是否厌倦了千篇一律的AI对话?是否渴望创造真正有灵魂的虚拟角…...
基于MATLAB的buck-boost升降压斩波电路系统设计 本设计包括设计报告,仿真工程
基于MATLAB的buck-boost升降压斩波电路系统设计 本设计包括设计报告,仿真工程。 Buck-Boost斩波电路是一种特殊的DC-DC转换器,它具备独特的功能,能够灵活地处理输入电压与输出电压之间的关系。 这种电路不仅能够将输入电压降至低于输出电压的…...
3个消息保护痛点解决方案:RevokeMsgPatcher本地消息留存技术全解析
3个消息保护痛点解决方案:RevokeMsgPatcher本地消息留存技术全解析 【免费下载链接】RevokeMsgPatcher :trollface: A hex editor for WeChat/QQ/TIM - PC版微信/QQ/TIM防撤回补丁(我已经看到了,撤回也没用了) 项目地址: https:…...
SOONet模型Python从入门到集成:环境配置与核心调用
SOONet模型Python从入门到集成:环境配置与核心调用 如果你刚接触AI模型,想用Python把SOONet这样的模型跑起来,可能会觉得有点无从下手。环境怎么配?依赖库怎么装?模型文件放哪里?代码怎么写?这…...
PowerBI进阶技巧:利用SWITCH函数实现动态自定义排序
1. 为什么需要自定义排序? 在PowerBI报表设计中,数据排序是最基础却最容易被忽视的功能。系统默认提供的升序和降序排列,就像餐厅里只有"辣"和"不辣"两种选项,而实际业务场景往往需要"微辣""中…...
终极BewlyBewly插件指南:5分钟打造个性化Bilibili界面
终极BewlyBewly插件指南:5分钟打造个性化Bilibili界面 【免费下载链接】BewlyBewly Improve your Bilibili homepage by redesigning it, adding more features, and personalizing it to match your preferences. 项目地址: https://gitcode.com/gh_mirrors/be/B…...
megaAVR_PWM硬件PWM库:工业级实时PWM控制详解
1. megaAVR_PWM 库深度技术解析:面向工业级实时控制的硬件PWM实现1.1 工程背景与核心价值定位在嵌入式系统开发中,PWM(脉宽调制)是电机驱动、LED调光、电源管理及伺服控制等场景的基础技术。然而,大量开发者仍依赖anal…...
SpringBoot+Vue实战:手把手教你搭建苍穹外卖后台管理系统(含Nginx配置避坑指南)
SpringBootVue全栈实战:从零构建外卖管理系统与Nginx部署精要 每次打开招聘网站,看到"要求有完整项目经验"的字样时,你是否也感到一阵心虚?作为全栈开发的学习者,我们往往陷入一个怪圈:学了很多碎…...
MusePublic效果展示:多主体构图稳定性测试——双人/三人场景自然互动生成
MusePublic效果展示:多主体构图稳定性测试——双人/三人场景自然互动生成 1. 引言:当AI学会描绘“关系” 在AI绘画的世界里,生成一个栩栩如生的人物已经不再是难事。但当画面中需要同时出现两个、甚至三个人物,并且他们之间要有…...
