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…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...
Python 高级应用10:在python 大型项目中 FastAPI 和 Django 的相互配合
无论是python,或者java 的大型项目中,都会涉及到 自身平台微服务之间的相互调用,以及和第三发平台的 接口对接,那在python 中是怎么实现的呢? 在 Python Web 开发中,FastAPI 和 Django 是两个重要但定位不…...
深度解析:etcd 在 Milvus 向量数据库中的关键作用
目录 🚀 深度解析:etcd 在 Milvus 向量数据库中的关键作用 💡 什么是 etcd? 🧠 Milvus 架构简介 📦 etcd 在 Milvus 中的核心作用 🔧 实际工作流程示意 ⚠️ 如果 etcd 出现问题会怎样&am…...
如何做好一份技术文档?从规划到实践的完整指南
如何做好一份技术文档?从规划到实践的完整指南 🌟 嗨,我是IRpickstars! 🌌 总有一行代码,能点亮万千星辰。 🔍 在技术的宇宙中,我愿做永不停歇的探索者。 ✨ 用代码丈量世界&…...
Android屏幕刷新率与FPS(Frames Per Second) 120hz
Android屏幕刷新率与FPS(Frames Per Second) 120hz 屏幕刷新率是屏幕每秒钟刷新显示内容的次数,单位是赫兹(Hz)。 60Hz 屏幕:每秒刷新 60 次,每次刷新间隔约 16.67ms 90Hz 屏幕:每秒刷新 90 次,…...
Netty自定义协议解析
目录 自定义协议设计 实现消息解码器 实现消息编码器 自定义消息对象 配置ChannelPipeline Netty提供了强大的编解码器抽象基类,这些基类能够帮助开发者快速实现自定义协议的解析。 自定义协议设计 在实现自定义协议解析之前,需要明确协议的具体格式。例如,一个简单的…...
vxe-table vue 表格复选框多选数据,实现快捷键 Shift 批量选择功能
vxe-table vue 表格复选框多选数据,实现快捷键 Shift 批量选择功能 查看官网:https://vxetable.cn 效果 代码 通过 checkbox-config.isShift 启用批量选中,启用后按住快捷键和鼠标批量选取 <template><div><vxe-grid v-bind"gri…...
