如何查询多级菜单(采用递归的方法)

应用场景
1.京东
京东的页面就是这么显示的在家用电器下面有电视.空调.洗衣机然后再电视下面又有全面屏电视.教育电视等等
在这里插入图片描述

2.我们的后端管理系统
我们后端在页面上显示的很多也是通过层级目录的显示出来。
如何实现

1.准备数据库

我们这里parent_id为0的为我们的一级菜单
在这里插入图片描述

2. 准备我们的实体类

注意我们需要编写一个List集合来放我们的二级集合,泛型为当前类
(实体类字段对应数据库字段即可,乱码是因为使用代码生成器,可能编码没有设置好)
注意:需要加上@TableField(exist = false) 代表数据库没有这个字段,不然会报错

package com.xue.entity;import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.experimental.Accessors;import java.io.Serializable;
import java.util.Date;
import java.util.List;/*** 产品类目*/
@Data
@Accessors(chain = true)
public class StuCategory implements Serializable {@TableId(value = "category_id", type = IdType.AUTO)private Long categoryId;@ExcelProperty("店铺id")private Integer shopId;@ExcelProperty("产品父id")private Integer parentId;@ExcelProperty("产品类目名字")private String categoryName;@ExcelProperty("产品图片")private String productImage;@ExcelProperty("创建时间")private Date createTime;@ExcelProperty("修改时间")private Date updateTime;@ExcelProperty("排序")private String sort;//编写一个list集合来放二级集合@TableField(exist = false)//代表数据库没有这个字段,不然会报错private List<StuCategory> children;
}

3.编写Controller

package com.xue.controller;import com.xue.entity.StuCategory;
import com.xue.service.StuCategoryService;
import com.xue.util.Result;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.util.List;@RestController
public class StuCategoryController {@Resourceprivate StuCategoryService stuCategoryService;/*** 查询所有分类以及子分类,并用树型结构组装起来* @return*/@GetMapping("StuCategoryList")public Result<List> StuCategoryList() {List<StuCategory> stuCategoryList = stuCategoryService.listwithTree();return Result.success(stuCategoryList);}}

4.编写Service方法

package com.xue.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.xue.entity.StuCategory;import java.util.List;public interface StuCategoryService extends IService<StuCategory> {List<StuCategory> listwithTree();
}

5.编写ServiceImpl

package com.xue.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xue.entity.StuCategory;
import com.xue.mapper.StuCategoryMapper;
import com.xue.service.StuCategoryService;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;@Service
public class StuCategoryServiceImpl extends ServiceImpl<StuCategoryMapper, StuCategory> implements StuCategoryService {@Resourceprivate StuCategoryMapper stuCategoryMapper;@Overridepublic List<StuCategory> listwithTree() {//查询出所有的分类List<StuCategory> stuCategoryList=stuCategoryMapper.selectList(null);/***     这段的代码的意思为调用了stream的filter过滤方法把查询出来getParentCid==0的数 因为这些都是我们的一级菜单*     然后查询还要查询出我们一级菜单下的二级菜单调用stream流下的map将我们的返回值重新改变一下在返回,这样把我们查询的数据set到我们的Children里面我们的Children为一个*     list集合,我们二级菜单的数据哪里来呢,我们就可以编写一个方法采用递归的方法查询出我们的二级菜单,我们二级菜单下面还有三级菜单*/List<StuCategory> stuCategories=stuCategoryList.stream().filter((StuCategory)->{return StuCategory.getParentId() == 0;}).map((menu) -> {//menu当前菜单在entities找下一个菜单menu.setChildren(getChildrens(menu, stuCategoryList));return menu;}).sorted((menu1, menu2) -> {return (menu1.getSort() == null ? 0 : Integer.parseInt(menu1.getSort())) - (menu2.getSort() == null ? 0 : Integer.parseInt(menu2.getSort()));}).collect(Collectors.toList());/**2.2查出我们的一级菜单下的子菜单 我们需要在实体类中编写一个list集合放我们的子菜单,因为一个一级菜单下面可以有多个二级菜单*/System.out.println(stuCategories);return stuCategories;}//递归查出所有的菜单的子菜单/*** @param root 为当前菜单* @param all  所有的菜单* @return* 首先调用stream的方法过滤一下  判断当前菜单的父id是否等于当前菜单的这个id。如果相同这个菜单就是这个id下的子菜单* 我们就调用map方法改变我们的返回值修改一下在重新返回,* map方法的作用为调用自己查询出下一级菜单 因为我们二级菜单下面可能有三级菜单或者四级菜单*/private List<StuCategory> getChildrens(StuCategory root, List<StuCategory> all) {List<StuCategory> children = all.stream().filter(stuCategory -> {return stuCategory.getParentId() == root.getCategoryId().intValue();}).map(categoryEntity -> {//还是调用这个setChildren方法添加我们的子菜单  参数为categoryEntity为当前的菜单找,在所有菜单中找到所有的子菜单//categoryEntity的意思  如果当前菜单为二级菜单就调用这个方法查询这个二级菜单下的子菜单categoryEntity.setChildren(getChildrens(categoryEntity, all));return categoryEntity;}).sorted((menu1, menu2) -> {return (menu1.getSort() == null ? 0 : Integer.parseInt(menu1.getSort())) - (menu2.getSort() == null ? 0 : Integer.parseInt(menu2.getSort()));}).collect(Collectors.toList());return children;}
}
注意我们这里使用到了jdk8中的stream
stream中的filter方法为过滤里面可以加条件
stream中的map方法为把我们返回的数据重新改变一下在返回可以set一些新的值返回
stream中的sorted方法为把查询出的数据以那种方式排序
stream.collect(Collectors.toList())为把查询出的数据已list集合返回

看看效果吧

{"code": 200,"msg": "成功","date": [{"categoryId": 1,"shopId": 1,"parentId": 0,"categoryName": "手机数码","productImage": null,"createTime": "2023-08-07T02:56:57.000+00:00","updateTime": "2023-08-07T02:57:00.000+00:00","sort": "1","children": [{"categoryId": 7,"shopId": 1,"parentId": 1,"categoryName": "手机通信","productImage": null,"createTime": "2023-08-07T03:00:58.000+00:00","updateTime": "2023-08-07T03:01:01.000+00:00","sort": "1","children": [{"categoryId": 8,"shopId": 1,"parentId": 7,"categoryName": "智能设备","productImage": null,"createTime": "2023-08-07T03:01:22.000+00:00","updateTime": "2023-08-07T03:01:23.000+00:00","sort": "1","children": []}]}]},{"categoryId": 2,"shopId": 1,"parentId": 0,"categoryName": "美妆护肤","productImage": null,"createTime": "2023-08-07T02:57:22.000+00:00","updateTime": "2023-08-07T02:57:25.000+00:00","sort": "1","children": []},{"categoryId": 3,"shopId": 1,"parentId": 0,"categoryName": "运动服饰","productImage": null,"createTime": "2023-08-07T02:57:37.000+00:00","updateTime": "2023-08-07T02:57:40.000+00:00","sort": "1","children": []},{"categoryId": 4,"shopId": 1,"parentId": 0,"categoryName": "酒水饮料","productImage": null,"createTime": "2023-08-07T02:58:19.000+00:00","updateTime": "2023-08-07T02:58:21.000+00:00","sort": "1","children": []},{"categoryId": 5,"shopId": 1,"parentId": 0,"categoryName": "珠宝钟表","productImage": null,"createTime": "2023-08-07T02:58:37.000+00:00","updateTime": "2023-08-07T02:58:39.000+00:00","sort": "1","children": []},{"categoryId": 6,"shopId": 1,"parentId": 0,"categoryName": "美味零食","productImage": null,"createTime": "2023-08-07T03:00:33.000+00:00","updateTime": "2023-08-07T03:00:36.000+00:00","sort": "1","children": []}]
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/65364.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python_day19_正则表达式

正则表达式re模块 导包 import res "python java c c python2 python python3"match 从头匹配 res re.match("python", s) res_2 re.match("python2", s) print("res:", res) print(res.span()) print(res.group()) print("…

Java 成功实现通过网址URL截图保存

Java 实现通过网址URL截图 1.DjNativeSwing方式 &#xff08;不好用&#xff09;2.phantomjs方式 &#xff08;截图还是有瑕疵&#xff09;3.selenium方式 &#xff08;满意&#xff0c;成功实现&#xff09;maven 引入下载相关浏览器chrome下载相关浏览器chromedriver驱动后端…

ElasticSearch学习

一&#xff0c;简介 ES&#xff08;elaticsearch简写&#xff09;&#xff0c; Elasticsearch是一个开源的高扩展的分布式全文检索引擎&#xff0c;它可以近乎实时的存储、检索数据&#xff1b;本身扩展性很好&#xff0c;可以扩展到上百台服务器&#xff0c;处理PB级别的数据…

9-数据结构-栈(C语言版)

数据结构-栈&#xff08;C语言版&#xff09; 目录 数据结构-栈&#xff08;C语言版&#xff09; 1.栈的基础知识 1.入栈&#xff0c;出栈的排列组合 情景二&#xff1a;Catalan函数&#xff08;计算不同出栈的总数&#xff09; 2.栈的基本操作 1.顺序存储 (1)顺序栈-定义…

c语言操作符

目录 运算符 移位操作符 左移操作符 右移操作符 位操作符 按位与& 按位或| 按位异或^ 异或交换数字 计算二进制中1的个数 关系操作符 逻辑操作符 条件操作符 逗号表达式 下标引用、函数调用和结构成员 隐式类型转换 整形提升实例&#xff1a; 算术转换 操作…

Java并发编程(四)线程同步 中 [AQS/Lock]

概述 Java中可以通过加锁&#xff0c;来保证多个线程访问某一个公共资源时&#xff0c;资源的访问安全性。Java提出了两种方式来加锁 第一种是我们上文提到的通过关键字synchronized加锁&#xff0c;synchronized底层托管给JVM执行的&#xff0c;并且在java 1.6 以后做了很多…

Flink窗口分类简介及示例代码

水善利万物而不争&#xff0c;处众人之所恶&#xff0c;故几于道&#x1f4a6; 文章目录 1. 流式计算2. 窗口3. 窗口的分类◆ 基于时间的窗口&#xff08;时间驱动&#xff09;1) 滚动窗口&#xff08;Tumbling Windows&#xff09;2) 滑动窗口&#xff08;Sliding Windows&…

ArcGIS Maps SDK for JavaScript系列之三:在Vue3中使用ArcGIS API加载三维地球

目录 SceneView类的常用属性SceneView类的常用方法vue3中使用SceneView类创建三维地球项目准备引入ArcGIS API创建Vue组件在OnMounted中调用初始化函数initArcGisMap创建Camera对象Camera的常用属性Camera的常用方法 要在Vue 3中使用ArcGIS API for JavaScript加载和展示三维地…

太牛了!国内版ChatDoc企业知识库,直接操作Doc、Docx、PDF、txt等文件

自ChatGPT问世以来&#xff0c;国外就有ChatPDF、ChatDOC等基于文档问答的项目&#xff0c;但是国内还一直处于对话类产品的研发中。 贵州猿创科技研发了基于本地向量模型的ChatDoc知识库系统&#xff0c;可以直接上传Doc、Docx、PDF、txt、网页链接等进行问答。 体验地址&…

【资讯速递】AI与人类思维的融合;OpenAI在中国申请注册“GPT-5”商标;移动大模型主要面向to B 智能算力是未来方向

2023年8月11日 星期五 癸卯年六月廿五 第000001号 欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 本文收录于IT资讯速递专栏,本专栏主要用于发布各种IT资讯&#xff0c;为大家可以省时省力的就能阅读和了解到行业的一些新资讯 资…

redis的基础命令01

1、操作库的指令 1、清除当前库---flushdb 2、清除所有库---flushAll 2、操作key的指令 最常用的指令get、set 1&#xff09;set key value 2&#xff09;get key 基础指令 1、del 删除单个&#xff1a;del key 、批量删除&#xff1a;del key1 key2 key3 2、exists 判断key是否…

1.作用域

1.1局部作用域 局部作用域分为函数作用域和块作用域。 1.函数作用域: 在函数内部声明的变量只能在函数内部被访问&#xff0c;外部无法直接访问。 总结&#xff1a; (1)函数内部声明的变量&#xff0c;在函数外部无法被访问 (2)函数的参数也是函数内部的局部变量 (3)不同函数…