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…...

华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...

vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...