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

Spring Data Redis 之使用RedisTemplate 实现自定义查询

Book实体类
95、Spring Data Redis 之使用RedisTemplate 实现自定义查询 及 Spring Data Redis 的样本查询_第1张图片

原本的接口,再继承我们自定义的接口
95、Spring Data Redis 之使用RedisTemplate 实现自定义查询 及 Spring Data Redis 的样本查询_第2张图片

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

95、Spring Data Redis 之使用RedisTemplate 实现自定义查询 及 Spring Data Redis 的样本查询_第3张图片

实现类:CustomBookDaoImpl

1、自定义添加hash对象的方法

95、Spring Data Redis 之使用RedisTemplate 实现自定义查询 及 Spring Data Redis 的样本查询_第4张图片


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

95、Spring Data Redis 之使用RedisTemplate 实现自定义查询 及 Spring Data Redis 的样本查询_第5张图片


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

95、Spring Data Redis 之使用RedisTemplate 实现自定义查询 及 Spring Data Redis 的样本查询_第6张图片
成功添加hash对象到redis数据库
95、Spring Data Redis 之使用RedisTemplate 实现自定义查询 及 Spring Data Redis 的样本查询_第7张图片

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

95、Spring Data Redis 之使用RedisTemplate 实现自定义查询 及 Spring Data Redis 的样本查询_第8张图片
结果:
数据:价格有100, 200 ,300这三个
在这里插入图片描述
结果正确,因为自定义的查询,是价格 > , 不是 >= 。
95、Spring Data Redis 之使用RedisTemplate 实现自定义查询 及 Spring Data Redis 的样本查询_第9张图片




Spring Data Redis 的样本查询

如图:因为bookDao有继承这个 QueryByExampleExecutor 接口,所以可以进行样本查询
在这里插入图片描述

样本中只有 name 作为参数来查询
95、Spring Data Redis 之使用RedisTemplate 实现自定义查询 及 Spring Data Redis 的样本查询_第10张图片

样本中只有 author 作为参数来查询
95、Spring Data Redis 之使用RedisTemplate 实现自定义查询 及 Spring Data Redis 的样本查询_第11张图片

完整代码

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
{
    @Id
    private Integer id; //即使这里类型是Integer,可是存到redis后,也会变成String类型

    //Indexed 指定对普通类型的属性建立索引,索引化后的属性才可用于查询。
    @Indexed
    private String name;
    @Indexed
    private 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对象的方法
    @Override
    public void hmset(String key, Map<String, String> value)
    {
        //调用 HashOperations 的方法来向数据库中存入 Hash 对象
        //要操作的value的类型是hash对象,就用.opsForHash() 方法
        stringRedisTemplate.opsForHash().putAll(key, value);
    }


    //自定义查询价格高于某个点的Book对象
    @Override
    public List<Book> findByPriceGt(double startPrice)
    {
        //由于 price 没有用注解@Indexed 建立索引,因此不能直接根据price来查询
        //首先获取全部的Book对象,redis会自动把我们添加的所有Book对象中的id,都存在一个set集合里面,因此先把id从set集合中都拿出来
        //要操作的value的类型是 set 集合,就用.opsForSet() 方法,此处的 books 就是 Book对象上 @RedisHash("books") 所指定的key
        Set<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获取所有的实体对象Book
        for (String id : idSet)
        {
            //key 为 "books:" 对应的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


    //=========================================样本查询=========================================

    @Autowired
    private BookDao bookDao;


    //==========================自定义查询================================

    //自定义添加hash对象的方法
    @Test
    public 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>

你可能感兴趣的:(springboot,spring,redis,java,SpringDataRedis,样本查询)