java实现多层级目录树详解

news/2024/5/17 20:38:45/文章来源:https://blog.csdn.net/zhenghuishengq/article/details/127211664

一,引言

在开发中,经常遇到前端需要实现一个多层级的目录树,那么后端就需要根据这种结构返回对应的数据,因此在这里记录一下本人在开发中是如何实现这个多层级的目录树。

二,建表建库

在建表时,需要注意的是一定要一个Pid和当前id,这样用于实现这个子级和父级的关联。建表语句如下

xCREATE TABLE `site` (  `id` bigint(20) NOT NULL AUTO_INCREMENT, `pid` bigint(20) DEFAULT NULL COMMENT '父id', `p_name` varchar(50) DEFAULT NULL COMMENT '父名称', `current_name` varchar(50) DEFAULT NULL COMMENT '当前层级名称', `created_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间', `updated_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `is_deleted` tinyint(4) DEFAULT NULL COMMENT '是否删除', PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=35 DEFAULT CHARSET=utf8;

在这里插入图片描述

可以参考一下我的,也可以自己插入一些数据。接下来插入数据

insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (0,'顶级','江西',now(),now(),0);
insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (0,'顶级','广东',now(),now(),0);
insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (0,'顶级','湖南',now(),now(),0);
insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (0,'顶级','河北',now(),now(),0);insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (1,'江西','南昌',now(),now(),0);
insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (1,'江西','赣州',now(),now(),0);
insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (1,'江西','九江',now(),now(),0);
insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (1,'江西','佛山',now(),now(),0);insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (2,'广东','广州',now(),now(),0);
insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (2,'广东','深圳',now(),now(),0);
insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (2,'广东','佛山',now(),now(),0);
insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (2,'广东','东莞',now(),now(),0);insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (3,'湖南','长沙',now(),now(),0);
insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (3,'湖南','湘潭',now(),now(),0);
insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (3,'湖南','岳阳',now(),now(),0);insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (4,'河北','唐山',now(),now(),0);
insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (4,'河北','石家庄',now(),now(),0);
insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (4,'河北','保定',now(),now(),0);insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (10,'深圳',,'南山',now(),now(),0);
insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (10,'深圳',,'福田',now(),now(),0);
insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (10,'深圳',,'宝安',,now(),now(),0);
insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (10,'深圳',,'龙岗',now(),now(),0);
insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (10,'深圳',,'龙华',now(),now(),0);
insert into site (pid,p_name,current_name,created_time,updated_time,is_deleted) VALUES (10,'深圳',,'光明',now(),now(),0);

在这里插入图片描述

三,原理

就是利用递归思想,将所有的数据遍历,然后是否有其他结点的Pid为当前结点的id,因此这个数据库的表一定要有一个pid。其实就是类似于两个嵌套的for循环,一个用于遍历,一个用于查找。如果查找成功,那么将那个结点做为当前结点的子节点

for(int i = 0; i < list.size; i++){for(int j = 0; j < list.size; j++){...}
}

就是将之前在集合中全部零散的结点,变成一棵树状型的树。然后这个1,4结点就是最上面的顶层结点,其他结点依次遍历加入到这两棵子树的后面,最后将这两棵树加入到一个集合里面,就变成了一棵大树。也可以参考一下后面的代码,将这个原理再理解一下。
在这里插入图片描述

四,代码实现

这里主要使用springboot项目,依赖和数据库连接之类的暂时不讲。可以参考一下我之前写的这篇https://blog.csdn.net/zhenghuishengq/article/details/109510128?spm=1001.2014.3001.5502

1,实体类

/*** @author zhenghuisheng* @date : 2022/10/8*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Site implements Serializable {public String id;public String pid;public String pname;public String currentName;public Date createdTime;public Date updatedTime;public Integer isDeleted;
}

2、dto类

对应上面的实体类,并在里面加入一个siteDtoList字段,用于保存当前结点的子集。

@Data
public class SiteDto implements Serializable {private static final long serialVersionUID = 1L;//用户idpublic String id;//父idpublic String pid;//父级namepublic String pname;//当前名称public String currentName;//创建时间public String createdTime;//更新时间public String updatedTime;//是否删除public Integer isDeleted;//子集,用于存储当前目录下面的全部子集public List<SiteDto> siteDtoList;
}

3,mybatis里面的sql

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.SiteMapper"><resultMap id="baseMap" type="com.example.demo.pojo.Site"><id column="id" property="id"></id><result column="pid" property="pid"></result><result column="p_name" property="pname"></result><result column="current_name" property="currentName"></result><result column="created_time" property="createdTime"></result><result column="updated_time" property="updatedTime"></result><result column="is_deleted" property="isDeleted"></result></resultMap><select id="queryAll" resultMap="baseMap" resultType="com.example.demo.pojo.Site">select * from site where is_deleted = 0;</select></mapper>

4,Mapper类

/*** @author zhenghuisheng* @date : 2022/10/8*/
@Repository
@Mapper
public interface SiteMapper {List<Site> queryAll();
}

5,service类

把这个看懂就基本上没问题了

/*** @author zhenghuisheng* @date : 2022/10/8*/
@Service
public class SiteService {@Autowiredprivate SiteMapper siteMapper;public List<SiteDto> queryAll(){List<SiteDto> datas = new ArrayList<>();//获取全部数据List<Site> siteList = siteMapper.queryAll();if (siteList != null){//将这个数据赋值到dto里面List<SiteDto> siteDtoList = siteList.stream().map(site -> {SiteDto siteDto = new SiteDto();BeanUtils.copyProperties(site,siteDto);//时间格式化siteDto.setCreatedTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(site.createdTime));siteDto.setUpdatedTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(site.updatedTime));return siteDto;}).collect(Collectors.toList());//遍历全部的数据,利用递归思想,获取全部的子集siteDtoList.forEach(e ->{//判断当前id是否为其他数据的父idList<SiteDto> childrenList = getChildrenList(e.getId(), siteDtoList);//设置子集,如果到了最后一级,那么直接设置为null,不展示这个属性即可e.setSiteDtoList(childrenList != null ? childrenList : null);});//获取所有的顶点数据,即最上层数据,该数据的pid为0List<SiteDto> siteDtoParents = siteDtoList.stream().filter(t -> t.getPid().equals("0")).collect(Collectors.toList());datas.addAll(siteDtoParents);}return datas;}//获取全部的子集合public static List<SiteDto> getChildrenList(String id,List<SiteDto> list){//便利全部数据,将需要的数据过滤出来return list.stream().filter(t-> t.getPid().equals(id)).collect(Collectors.toList());}
}

7,Contrller类测试

/*** @author zhenghuisheng* @date : 2022/10/8*/
@RestController
public class SiteController {@Autowiredprivate SiteService siteService;@RequestMapping("/getAllData")public List<SiteDto> getAllData(){return siteService.queryAll();}
}

用postman测试一下,结果就出来了
在这里插入图片描述
这样就大功告成了!!

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

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

相关文章

(附源码)计算机毕业设计SSM悠哈出租车管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

模拟IC设计到底怎么学?给初学者一点建议

想必大家都知道&#xff0c;模拟IC设计非常难学。就拿最普遍的晶体管来说&#xff0c;我们分析它的时候必须首先分析直流偏置&#xff0c;其次在分析交流输出电压。可以说&#xff0c;这是一项相当复杂的工作。有些朋友一直吐槽模拟IC设计真的非常难学&#xff0c;那么到底该怎…

SWAT模型 建模方法、实例应用、高级进阶

目录 第一部分&#xff1a;【建模及实践】SWAT模型在水文水资源、面源污染模拟中的实践技术应用及典型案例分析 第二部分&#xff1a;【高级进阶】SWAT模型高阶应用暨无资料地区建模、不确定分析与气候变化、土地利用对面源污染影响模型改进及案例分析 基于ArcGIS的SWAT模型是…

yolov5-6.1的完全使用手册,含模型训练测试(可训练自己的数据集)

安装yolov5 安装命令如下下所示&#xff0c;包含了下载yolov5-6.1&#xff0c;及相关包安装命令。yolov5项目目前已经更新到6.2&#xff0c;支持对图像数据的分类&#xff0c;但使用较为麻烦&#xff0c;因此仅以6.1为例进行说明。安装yolov5后&#xff0c;切记不要安装wandb&…

条件区域循环的Sumif

问题:Sumif条件为D12:D16,求和区域从E3:E8向右,条件区域为B3:D8三列循环 函数解决:=SUMIF(OFFSET($B$3:$B$8,,MOD(COLUMN(C1),3)),$D12,E$3:E$8) 思路: 利用Mod(Column(C1),3),右拉生成0、1、2、0、1、2……这样的循环数 利用Offset,从B3:B8起,右拉生成向右偏移0、1、…

国民技术MCU之串口烧录

国民技术MCU串口烧录 前言 在我们使用国民技术单片机的时候&#xff0c;一般是用JLink SWD来烧录调试固件。 但是在某些情况下&#xff0c;比如需要刷写固件的现场没有JLink工具&#xff0c;采用批量生产、或者MCU在程序上电后SWD功能没有正常运行&#xff08;变砖&#xff0…

数据库概述06(视图)

视图 常见的数据库对象 表TABLE 表是存储数据的逻辑单元&#xff0c;以行和列的形式存在&#xff0c;列就是字段&#xff0c;行就是记录 数据字典 就是系统表&#xff0c;存放数据库相关信息的表。系统表的数据通常由数据库系统维护&#xff0c;程序员通常不应该修改&#xf…

一些有关多线程的‘‘八股文‘‘?!

目录 一. 常见的锁策略: 二. CAS 三.synchronized原理 四. HashTable, HashMap, ConcurrentHashMap 之间的区别: 五. 死锁的成因, 和解决方案: 一. 常见的锁策略: 1.乐观锁 vs 悲观锁: 描述的是两种不同的加锁态度 乐观:预测锁冲突概率不高,因此做的工…

2022年NPDP新版教材知识集锦--【第一章节】(2)

【制定战略的工具】 SWOT分析&#xff1a;由四个英文单词的首字母组合而成&#xff0c;分别是优势(Strengths)、劣势(Weaknesses)、机会(Opportunities)和威胁(Threats)。 ⚫优势&#xff1a;某企业或项目优于其他企业或项目的特点。 ⚫劣势&#xff1a;某企业或项目不如其他…

python学习笔记:numpy库,使用matpotlib库绘图

目录 一.Numpy库 1.什么是numpy? 2.Numpy数组和原生Python array数组之间的区别 3.Numpy数组 ​编辑 4.numpy数组的运算 5.numpy的索引&#xff0c;切片 二.matplotlib 1.绘制直线 2.绘制曲线 3.散点图绘制 4.多界面绘制 5.柱形图绘制 6.3D图形绘制 一.Numpy库 1.…

数据库与MPP数仓(三十):pigsty部署

pigsty是pg的开箱即用版本,提供完善监控和高可用功能,高质量的国产开源工程,监控面板非常详尽,保姆级别的文档; 参考:腾讯云VPC部署 | Pigsty 参考:Releases Vonng/pigsty GitHub pigsty源码基本上都是使用ansible的playbook编写,使用ansible同时配置多台机器,在角…

基于Ubuntu20.04安装Nvidia驱动、Cuda和CudNN

基于Ubuntu20.04安装Nvidia驱动、Cuda和CudNN 前言 nvidia驱动&#xff0c;cuda&#xff0c;cudnn三者关系 1 nvidia驱动 1.1 nvidia驱动安装 首先Nvidia驱动应该是最好理解的&#xff0c;它就是GPU显卡的软件驱动程序&#xff0c;和计算机其他的硬件驱动一样。Nvidia官网提…

设计管理工具的三个基本类别

什么是用于管理设计过程的优质设计管理工具?成功管理设计项目需要正确的工具和软件。设计管理工具的三个基本类别是&#xff1a;通讯工具、时间线管理工具、文件和资源管理工具。 1、通讯工具 沟通工具使团队成员能够保持在同一页面上&#xff0c;无论他们的工作地点如何。他们…

app自动化测试之Andriod WebView如何测试

Hybrid App&#xff08;混合模式移动应用&#xff09;是介于 Web-app、Native-app 之间的 app&#xff0c;本质上是 Native-app 中嵌入 WebView 组件&#xff0c;在 WebView 组件里可以访问 Web App。Hybrid App 在给用户良好交互体验的同时&#xff0c;还具备了 Web App 的跨平…

在RTL书写中如何考虑延迟,面积等

在RTL书写中如何考虑延迟&#xff0c;面积等 文章目录在RTL书写中如何考虑延迟&#xff0c;面积等reference在RTL编码中考虑时延对多if语句&#xff1a;对单if语句case和if嵌套“先加后选”和“先选后加”调整计算顺序在RTL编码中考虑面积操作符优化资源共享多比特逻辑优化在RT…

查找

查找 查找元素伪代码 穷举法 BeginSet num[length] to some numberSet targetSet i to 0read targetwhile (i <length) doif(num[i] == target)printf("找到了")breakif(i==length)printf("没找到") 二分法 BeginSet num[length] to some numberSet tar…

毕业设计 单片机stm32的工厂环境检测系统 - 嵌入式 物联网 单片机

文章目录0 前言1 简介2 主要器件3 实现效果4 设计原理4.1 BH1750光照模块4.2 RC5224.3 DHT11温湿度传感器4.4 MQ-2烟雾传感器5 部分核心代码5 最后0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0…

艾美捷D3204 2‘-脱氧胸苷(胸苷)中文说明书

艾美捷D3204 2-脱氧胸苷&#xff08;胸苷&#xff09;同义词&#xff1a; 胸苷; dT; 1-(2-脱氧-b-呋喃核糖基)-5-甲基尿嘧啶&#xff1b;1-(2-脱氧-bD-呋喃核糖基)-5-甲基尿嘧啶&#xff1b;2-脱氧-D-胸苷&#xff1b;b-胸苷&#xff1b;D-胸苷&#xff1b;胸腺嘧啶脱氧核苷&a…

【Django框架】——04 创建Django项目子应用

文章目录创建Django项目子应用1.创建⼦应⽤2.⼦应⽤⽬录说明3.注册安装⼦应⽤4.设置PyCharm的环境创建Django项目子应用 在Web应⽤中&#xff0c;通常有⼀些业务功能模块是在不同的项⽬中都可以复⽤的&#xff0c;故在开发中通常将⼯程项⽬拆分为不同的⼦功能模块&#xff0c;…

本地存储(localStorage和sessionStorage)

session 一段时间 local 本地的&#xff1b;当地的 1、 生命周期永久生效&#xff0c;除非手动删除&#xff0c;否则关闭页面也会存在 2、可以多窗口&#xff08;页面&#xff09;共享&#xff08;同一浏览器可以共享&#xff09; 3、以键值对的形式存…