SpringBoot 查询redis 数据进行分页

  • Post author:
  • Post category:其他

查询redis 分页工具类

1.PageUtil

package com.demo.admin.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @description: redis分页工具
 * @author: fcy
 * @time: 2022/2/14 13:37
 */
@Component
public class PageUtil {
    @Resource
    private RedisTemplate redisTemplate;

    /**
     * 存放单个hash缓存
     *
     * @param key   键
     * @param hkey  键
     * @param value 值
     * @return
     */
    public boolean hput(String key, String hkey, Object value) {
        try {
            redisTemplate.opsForHash().put(key, hkey, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 分页存取数据
     *
     * @param key   hash存取的key
     * @param hkey  hash存取的hkey
     * @param score 指定字段排序
     * @param value
     * @return
     */
    public boolean setPage(String key, String hkey, double score, String value) {
        boolean result = false;
        try {
            result = redisTemplate.opsForZSet().add(key + ":page", hkey, score);
            //result = hput(key, hkey, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //设置辅助分页的过期时间
        redisTemplate.expire(key + ":page", 1800000, TimeUnit.MILLISECONDS);
        //redisTemplate.expire(key,60000 , TimeUnit.MILLISECONDS);
        return result;
    }

    /**
     * 分页取出 hash中hkey值
     *
     * @param key
     * @param offset
     * @param count
     * @return
     */
    public Set<String> getPage(String key, int offset, int count) {
        Set<String> result = null;
        try {
            result = redisTemplate.opsForZSet().rangeByScore(key + ":page", 1, 100000, (offset - 1) * count, count);//1 100000代表score的排序氛围值,即从1-100000的范围
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 计算key值对应的数量
     *
     * @param key
     * @return
     */
    public Integer getSize(String key) {
        Integer num = 0;
        try {
            Long size = redisTemplate.opsForZSet().zCard(key + ":page");
            return size.intValue();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return num;
    }
}

1.RedisFurryAndPageQueryUtil

package com.demo.admin.util;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.demo.admin.api.entity.otc.OtcAssetsInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;

/**
 * @description:
 * @author: fcy
 * @time: 2022/2/14 13:47
 */
@Component
public class RedisFurryAndPageQueryUtil<T> {
    /**
     * 插入辅助分页
     */
    @Resource
    private PageUtil pageUtil;
    /**
     * 注入redis模板工具
     */
    @Resource
    private RedisTemplate redisTemplate;


    /**
     * 根据条件进行模糊查询查询并返回分页结果
     *
     * @param name
     * @param currentPage
     * @param count
     * @return
     */
    public Page<T> find(String name, int currentPage, int count, String tableName, T t) {
        //将传入的参数变为小写
        name = StringUtils.lowerCase(name);
        //map用来存储查询到的结果以及分页的总数据
//        Map<String, Object> map = new HashMap<>();
        Page<T> page = new Page<T>();
        //用来存储查询到的ZhDicGoods
        ArrayList<OtcAssetsInfo> result = new ArrayList<>();
        //定义pageName用来查看redis中是否存在对应的辅助分页key-value
        String pageName = tableName + name + ":page";
        //是否存在对应的辅助分页辅助分页key-value
        Boolean ifExist = redisTemplate.hasKey(pageName);
        //如果不存在,生成辅助分页,同时查询
        if (!ifExist) {
            try {
             Cursor<Map.Entry<String, String>> cursor = null;
                //如果传入参数为空则查询所有
                if (name == null || "".equals(name)) {
                    //模糊查询返回结果
                    //Cusor中存储的是查询key对应的Map
                    cursor = redisTemplate
                            .opsForHash()
                            //绑定模糊查询的hash的key
                            .scan(tableName, ScanOptions.scanOptions()
                                    //模糊查询规则
                                    .match("*")
                                    .count(1000).build());
                }else{
                
                //模糊查询返回结果
                //Cusor中存储的是查询key对应的Map
                cursor = redisTemplate
                        .opsForHash()
                        //绑定模糊查询的hash的key
                        .scan(tableName, ScanOptions.scanOptions()
                                //模糊查询规则
                                .match("*"+name + "*")
                                .count(10000).build());
                //生成分页key-value
                setPage(cursor, name, tableName);
                //生成查询结果并且放入map中
                getPageResult(name, currentPage, count, page, result, tableName, t);
                }
                cursor.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            //有辅助分页key-value,直接查询结果放入map中
            getPageResult(name, currentPage, count, page, result, tableName, t);
        }
        //返回result
        return page;

    }


    /**
     * 生成辅助分页
     *
     * @param cursor
     * @param name:会在pageutil中自动加上:page
     */
    private void setPage(Cursor<Map.Entry<String, String>> cursor, String name, String tableName) {
        //setPage初始化值,zset的sort值
        int i = 1;
        //遍历模糊查询结果,将模糊查询的结果生成分页数据,用zset存储模糊查询的数据排序
        //存储名称是查询name+:page,值是hash类型的key
        while (cursor.hasNext()) {
            Map.Entry<String, String> result = cursor.next();
            //获取key
            String key = result.getKey();
            //存储对应的辅助分页数据
            pageUtil.setPage(tableName + name, key, i, null);
            i++;

        }
    }


    /**
     * 获取分页的总数据,并且加入到map中
     *
     * @param name
     * @param currentPage
     * @param count
     * @param page
     * @param result
     */
    private void getPageResult(String name, int currentPage, int count, Page<T> page, ArrayList result, String tableName, T t) {

        //得到分页数据总条数
        Integer totalNumber = pageUtil.getSize(tableName + name);
        //得到对应分页的key数组
        Set<String> keyPages = pageUtil.getPage(tableName + name, currentPage, count);
        //遍历循环查询对应cout对应的数据,同时转为对象输入到List
        count = keyPages.size();
        for (String keyPage : keyPages) {
            //根据zset的key查询hash对应的数据
            T Object = (T) redisTemplate.boundHashOps(tableName).get(keyPage);
            result.add(Object);
        }
        //返回总页数
        Integer pageCount = 0;
        if (totalNumber % count == 0) {
            pageCount = totalNumber / count;
        } else {
            pageCount = totalNumber / count + 1;
        }
        //加入返回实体类结果,总条数,起始页数,总条数
        page.setCurrent(currentPage);
        page.setSize(count);
        page.setRecords(result);
        page.setTotal(totalNumber);
        page.setPages(pageCount);
    }
}


junit 单元测试

package test;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.demo.admin.DemoApplication;
import com.demo.admin.api.entity.otc.OtcAssetsInfo;
import com.demo.admin.util.RedisFurryAndPageQueryUtil;
import com.demo.common.core.util.JsonMapper;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import java.util.Map;

/**
 * @author :fcy
 * @date :Created in 2022/2/15 17:04
 * @description:
 * @modified By:
 */

@Slf4j
@SpringBootTest(classes = DemoApplication.class)
// 让 JUnit 运行 Spring 的测试环境, 获得 Spring 环境的上下文的支持
@RunWith(SpringRunner.class)
public class MethodTestUtils {
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private RedisFurryAndPageQueryUtil redisFurryAndPageQueryUtil;
    @Test
    public void testRedisPage(){
        String tableName = "otcAssetsInfo";
//        for (int i = 0; i < 25; i++) {
//            OtcAssetsInfo otcAssetsInfo = new OtcAssetsInfo();
//            otcAssetsInfo.setUnderlyingCode("123"+i);
//            otcAssetsInfo.setUnderlyingName("测试资产1"+i);
//            redisTemplate.opsForHash().put(tableName,otcAssetsInfo.getUnderlyingName(),otcAssetsInfo);
//        }
        Page<OtcAssetsInfo> page = redisFurryAndPageQueryUtil.find("", 1, 10, tableName, OtcAssetsInfo.class);

        log.info(JsonMapper.INSTANCE.toJson(page));
        log.info(JsonMapper.INSTANCE.toJson(page.getRecords()));
    }
}

想学习,关注微信公众号 “Java追求”


版权声明:本文为qq_42274641原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。