Redis实战-类目操作

类目简介

在这里插入图片描述
上述图片的箭头指向的便是类目

功能描述

  1. 添加类目:完成单个类目信息的录入
  2. 查询单个类目:根据类目主键查询类目详情信息以及它所对应的子类目信息
  3. 查询所有类目信息:查询出所有类目信息以及它的所有子类目信息

领域模型

将信息抽象为对应的领域模型

在这里插入图片描述

  • 定义子类目数据使用List类型是因为可能存在多个子类目
  • 为了方便查询我们在模型上加了父类目id,可以根据一个类目id即可查询其所有的子类目信息

类目基础操作

由于大型网站平台每天可能有上亿人访问,如果没访问一次类目就需要调用一次数据库,那这样对数据库的压力太大了

由于访问频次较高,所以对他进行优化需要使用Redis列表结构

列表头元素和尾元素:

  • 头元素指列表左端第一个元素
  • 尾元素指列表右端第一个元素

列表操作

1.插入数据

Redis列表结构就是List,现在将下面的信息录入到Redis中去
在这里插入图片描述

@Controller
public class CategoryApi {
    @Autowired
    private RedisTemplate redisTemplate;

    @PostMapping("/addList")
    @ResponseBody
    public Result add() {
        Result result = new Result();
        result.setSuccess(true);
        Category firstCategory = new Category();
        firstCategory.setId("gcl_001");
        firstCategory.setName("女装");
        firstCategory.setDescription("女装");

        Category secondCategory = new Category();
        secondCategory.setId("gcl_sub_001");
        secondCategory.setName("连衣裙");
        secondCategory.setParentCategoryId("gcl_001");
        secondCategory.setDescription("连衣裙");

        Category thirdCategory = new Category();
        thirdCategory.setId("gcl_sub_002");
        thirdCategory.setName("半身裙");
        thirdCategory.setParentCategoryId("gcl_001");
        thirdCategory.setDescription("半身裙");

        Category fouthCategory = new Category();
        fouthCategory.setId("gcl_sub_003");
        fouthCategory.setName("毛针织衫");
        fouthCategory.setParentCategoryId("gcl_001");
        fouthCategory.setDescription("毛针织衫");

        Category fifthCategory = new Category();
        fifthCategory.setId("gcl_sub_004");
        fifthCategory.setName("卫衣");
        fifthCategory.setParentCategoryId("gcl_001");
        fifthCategory.setDescription("卫衣");
//leftPush也就是从左到右依次插入数据
        redisTemplate.opsForList().leftPush("categoryList", firstCategory);
        redisTemplate.opsForList().leftPush("categoryList", secondCategory);
        redisTemplate.opsForList().leftPush("categoryList", thirdCategory);
        redisTemplate.opsForList().leftPush("categoryList", fouthCategory);
        redisTemplate.opsForList().leftPush("categoryList", fifthCategory);
        return result;
    }
}

使用Redis存储读取的对象必须都能够序列化,对象需要经过网络传输才能存到远程的Redis服务器中,所以Category需要实现java.io.Serializable接口,序列化的过程由RedisTemplate自动实现

2.查询数据
@PostMapping("/queryAll")
    @ResponseBody
    public Result<List<Category>> queryAll(){
        Result result = new Result();
        result.setSuccess(true);

        //查询所有的类目数据
        List<Category> categoryDatas = redisTemplate.opsForList().range("categoryList",0,-1);

        //处理父子类目关系
        List<Category> allFirstCats = handleParentData(categoryDatas);
        result.setData(allFirstCats);
        return result;
    }

    /**
     * 处理父子类目关系数据
     *
     * @param categoryDatas 一组类目数据
     */
    private List<Category> handleParentData(List<Category> categoryDatas){
        if (CollectionUtils.isEmpty(categoryDatas)){
            //防止空指针异常,返回一个没有元素的List
            return new ArrayList<>();
        }
        Map<String,Category> categoryMap = new HashMap<>();
        //初始化一个虚拟根节点,0 可以对应的是所有一级类目的父亲
        categoryMap.put("0",new Category());
        //把所有的类目转换为 map 数据
        categoryDatas.forEach(category -> categoryMap.put(category.getParentCategoryId(),category));
        //再次遍历类目数据,处理父子关系
        categoryDatas.forEach(category -> {
            // 得到父实例
            String pId = category.getParentCategoryId();
            // 没有父类目 Id,当做 0 处理,作为虚拟根节点的子类目,就是所有的一级类目
            if (StringUtils.isBlank(pId)) {
                pId = "0";
            }

            Category parent = categoryMap.get(pId);
            if (parent!=null){
                //初始化子类目
                if (parent.getSubCategoryList()==null){
                    parent.setSubCategoryList(new ArrayList<>());
                }
                //在父类目中添加子类目
                parent.getSubCategoryList().add(category);
            }
        });

        //得到所有的一级类目
        List<Category> data = categoryMap.get("0").getSubCategoryList();
        return data;
    }

range("categoryList",0,-1)方法的作用就是查询categoryList列表的的值

  • 第一个值是key
  • 第二个值是起始位置
  • 第三个值是结束位置.-1表示取得全部
3.删除数据
@GetMapping("/delListItem")
@ResponseBody
public Result<List<Category>> delListItem() {
    Result<List<Category>> result = new Result<>();
    result.setSuccess(true);
    redisTemplate.opsForList().leftPop("categoryList");
    redisTemplate.opsForList().rightPop("categoryList");
    List<Category> subCategoryLists = redisTemplate.opsForList().range("categoryList", 0, -1);
    result.setData(subCategoryLists);
    return result;
}
  • leftPop()删除头元素
  • rightPop()删除尾元素
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-irony-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值