Java开发树结构数据封装!
目录
- 源数据如下
- controller接口:
- service层封装:
- Dao接口:
- Dao层Mapper:
- 映射实体类:
源数据如下

controller接口:
@RequestMapping("/UserTreeInfo")public RespBody getUserTreeInfo(Long userId) {List<MenuTreeVo> userInfo = userInfoServiceimpl.getUserTreeInfo(userId);if (userInfo != null && userInfo.size() > 0) {return new RespBody(200,userInfo,"查询成功");}return new RespBody(501,null,"查询失败");}
service层封装:
package com.ekgc.qy.Service.impl;import com.ekgc.qy.Service.UserInfoService;
import com.ekgc.qy.dao.UserInfoDao;
import com.ekgc.qy.pojo.dto.MenuDto;
import com.ekgc.qy.pojo.vo.MenuTreeVo;
import jakarta.annotation.Resource;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.stereotype.Service;import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;/*** @author Magic* @version 1.0*/
@Service
public class UserInfoServiceimpl implements UserInfoService {@Resourceprivate UserInfoDao userInfoDao;@Overridepublic List<MenuTreeVo> findGetInfoByUserId(Long userId) {return userInfoDao.findGetInfoByUserId(userId);}/*** 查询树结构菜单* @return 返回树结构菜单*/@Overridepublic List<MenuTreeVo> getUserTreeInfo(Long userId) {//查出所有菜单和目录List<MenuDto> userTreeInfo = userInfoDao.getUserTreeInfo(userId);// 先过滤出所有的父菜单目录List<MenuDto> mulu = userTreeInfo.stream().filter(ml -> ml.getParentId() == 0).toList();return buildTrees(mulu,userTreeInfo);}private ArrayList<MenuTreeVo> buildTrees(List<MenuDto> data, List<MenuDto> menus) {// 存储树结构的菜单树ArrayList<MenuTreeVo> trees = new ArrayList<>();// 封装树结构菜单数据data.forEach(md -> {// 封装的MenuTreeVo树结构对象MenuTreeVo ml = new MenuTreeVo();// 根据属性名 将数据复制到另一个对象// 实现MenuDto到MenuTreeVo的转换try {BeanUtils.copyProperties(ml, md);//前一个是目标对象,后一个是源对象} catch (IllegalAccessException e) {throw new RuntimeException(e);} catch (InvocationTargetException e) {throw new RuntimeException(e);}//遍历目录和菜单找出子菜单并封装子菜单List<MenuDto> childs = new ArrayList<>();menus.forEach(m ->{if (m.getParentId() != null){if (m.getParentId().equals(md.getId())){childs.add(m);}}});// 没有子菜单 不继续执行递归if (!childs.isEmpty()) {ml.setChildMenus(buildTrees(childs, menus));}trees.add(ml);});return trees;}
}
Dao接口:
package com.ekgc.qy.dao;import com.ekgc.qy.pojo.dto.MenuDto;
import com.ekgc.qy.pojo.vo.MenuTreeVo;import java.util.List;/*** @author Magic* @version 1.0*/
public interface UserInfoDao {List<MenuTreeVo> findGetInfoByUserId(Long userId);List<MenuDto> getUserTreeInfo(Long userId);}
Dao层Mapper:
<?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属性 指定mapper映射对应的mapper接口是谁 -->
<mapper namespace="com.ekgc.qy.dao.UserInfoDao"><!-- id:重写的方法;
resultType:返回值类型。pojo实体类
resultMap 对应返回值类型需要手动指定
parameterType:对应方法参数类型
--><!-- 列表一对多嵌套--><resultMap id="roleMenus" type="MenuTreeVo"><id property="id" column="id"/><result property="menuName" column="menu_name"/><result property="permissions" column="permissions"/><collection property="childMenus" ofType="MenuDto" javaType="java.util.ArrayList"><id property="id" column="childId"/><result property="menuName" column="menuName"/><result property="menuUrl" column="menuUrl"/><result property="permissions" column="auth"/><result property="path" column="path"/><result property="parentId" column="parent_id"/></collection></resultMap><!-- colection1对多查询--><select id="findGetInfoByUserId" resultMap="roleMenus">SELECT ml.id,ml.menu_name,ml.permissions,sy.id AS childId,sy.menu_name AS menuName,sy.menu_url AS menuUrl,sy.permissions AS auth,sy.path,sy.parent_id FROM sys_menu sy,(SELECT sm.id,menu_name,permissions FROM sys_menu smLEFT JOIN sys_role_menu srm ON sm.id = srm.menu_idLEFT JOIN sys_role sr ON srm.role_id = sr.idLEFT JOIN sys_user su ON su.user_type = sr.idWHERE su.id = #{userId}) AS ml WHERE ml.id = sy.parent_id</select><select id="getUserTreeInfo" resultType="com.ekgc.qy.pojo.dto.MenuDto">SELECT sm.id,menu_name,menu_url,path,permissions,parent_id FROM sys_menu smLEFT JOIN sys_role_menu srm ON sm.id = srm.menu_idLEFT JOIN sys_role sr ON srm.role_id = sr.idLEFT JOIN sys_user su ON su.user_type = sr.idWHERE su.id = #{userId} AND menu_name like concat("%",#{menuName},"%")</select>
</mapper>
映射实体类:
实体类只要有sql查询到的字段(id,menu_name,menu_url,path,permissions,parent_id)有就可以映射,不能缺少某个字段否则映射不了!
package com.ekgc.qy.pojo.vo;import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;import java.util.ArrayList;/*** @author Magic* @version 1.0*/
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class MenuTreeVo {private Long id;private String menuName;private String menuUrl;private String permissions;private String path;private Long parentId;private ArrayList<MenuTreeVo> childMenus;
}
相关文章:
Java开发树结构数据封装!
目录 源数据如下controller接口:service层封装:Dao接口:Dao层Mapper:映射实体类: 源数据如下 controller接口: RequestMapping("/UserTreeInfo")public RespBody getUserTreeInfo(Long userId) {List<MenuTreeVo>…...
c++学习笔记汇总
[TOC] (C学习笔记汇总) 基础认识、基础语法 类、类与类之间的关系、可调用对象、std::function类模板、c11新标准、资源管理方案RAII、指针、智能指针、引用计数、C的多态 ios、istream、iostream、fstream、sstream 模板编程: 模板编程:主要分为“泛…...
[动手学深度学习]生成对抗网络GAN学习笔记
论文原文:Generative Adversarial Nets (neurips.cc) 李沐GAN论文逐段精读:GAN论文逐段精读【论文精读】_哔哩哔哩_bilibili 论文代码:http://www.github.com/goodfeli/adversarial Ian, J. et al. (2014) Generative adversarial network…...
Kotlin中的算数运算符
在Kotlin中,我们可以使用各种算术运算符来进行数值计算和操作。下面对这些运算符进行详细描述,并提供示例代码。 正号(正数)和负号(负数): 正号用于表示一个正数,不对数值进行任何…...
Linux高性能服务器编程 学习笔记 第十六章 服务器调制、调试和测试
Linux平台的一个优秀特性是内核微调,即我们可以通过修改文件的方式来调整内核参数。 服务器开发过程中,可能会碰到意想不到的错误,一种调试方法是用tcpdump抓包,但这种方法主要用于分析程序的输入和输出,对于服务器的…...
第三期:云函数入门指南答案
1.云函数需要用户自行考虑租用/购买多少资源以达到最少成本最高效运行自己的函数。 答案:错误(False) 2.Cloud Functions可以为您准备好计算资源,弹性地、可地运行任务,并提供日志查询、性能监控和报警等功能。 答案:正确(True…...
企业怎么通过数字化工具来实现数字化转型?
数字化转型是使用数字技术和工具从根本上改变公司运营方式并向客户提供价值的过程。它涉及思维方式、流程和技术的全面转变,以跟上快节奏的数字时代。以下是有关公司如何通过数字工具实现数字化转型的分步指南: 1.定义您的愿景和目标: 首先确…...
React函数式写法和类式写法的区别(以一个计数器功能为例子)
函数式写法更加简洁和函数式编程思维导向,适用于无状态、UI纯粹的组件,且可以使用Hooks处理副作用。而类式写法适用于有内部状态、生命周期方法和复杂交互逻辑的组件,提供了更多的灵活性和控制力。 文章目录 一、计数器功能演示 1.函数式写法…...
【根据国防科大学报官网word模板修改的Latex模板】
根据国防科大学报官网word模板修改的Latex模板 学报Word模板链接Latex模板结构编译环境为Texlivevscode或Textstudio 学报Word模板链接 学报官网相关下载链接 点击链接即可前往官网下载相关word模板 Latex模板结构 latex模板 ass.cfg文件 %深层模板文件ass.cls文件 %浅层模板…...
系列十一、Redis中分布式缓存实现
一、缓存 1.1、什么是缓存 内存就是计算机内存中的一段数据。 1.2、内存中的数据特点 读写快断电数据丢失 1.3、缓存解决了什么问题 提高了网站的吞吐量和运行效率减轻了数据库的访问压力 1.4、哪些数据适合加缓存 使用缓存时,一定是数据库中的数据极少发生改…...
Spark大数据分析与实战笔记(第一章 Scala语言基础-4)
文章目录 每日一句正能量1.4 Scala面向对象的特性1.4.1 类与对象的特性1.4.2 继承1.4.3 单例对象和伴生对象1.4.4 特质 每日一句正能量 若要快乐,就要随和;若要幸福,就要随缘。快乐是心的愉悦,幸福是心的满足。别和他人争吵&#…...
腾讯云服务器端口localhost可以访问,外部无法访问解决
搭建frp跳板,发现无法使用。ssh 连接不上。 主要检查2个东西: 1. ubuntu ufw系统防火墙。这个默认是关掉的 2. tencent这个防火墙规则设置后,还要设置到实例上。 以前不是这样的。就掉坑里了。 # systemctl rootVM-4-4-ubuntu:/lib/syst…...
【软考-中级】系统集成项目管理工程师 【16 变更管理】
持续更新。。。。。。。。。。。。。。。 【第十六章】变更管理 (选择2分 考点 1:变更的常见原因考点 2:变更管理的原则是项目基准化、变更管理过程规范化考点 3考点 4考点 5:变更的工作程序考点 6考点 7考点 8考点 9考点 10考点 11考点 12:变更分类系列文章经典语录 考点 1:变…...
【Eclipse】查看版本号
1.在Eclipse的启动页面会出现版本号 2. Eclipse的关于里面 Help - About Eclipse IDE 如下图所示,就为其版本 3.通过查看readme_eclipse.html文件...
论文精讲目录
ViT论文逐段精读【论文精读】MoCo 论文逐段精读【论文精读】对比学习论文综述【论文精读】Swin Transformer论文精读【论文精读】CLIP 论文逐段精读【论文精读】双流网络论文逐段精读【论文精读】I3D 论文精读【论文精读】视频理解论文串讲(上)【论文精读…...
双飞翼布局和圣杯布局
双飞翼布局和圣杯布局都是一种三栏布局,其中主要内容区域位于中间,左侧栏和右侧栏位于两侧。它们的实现方式类似,但有一些细微的差别。 双飞翼布局的实现原理是通过使用flex布局,给主要内容区域设置flex:1;…...
Hive insert插入数据与with子查询
1. insert into 与 insert overwrite区别 insert into 与 insert overwrite 都可以向hive表中插入数据,但是insert into直接追加到表中数据的尾部,而insert overwrite会重写数据,既先进行删除,再写入 注意:如果存在分…...
如何在Django中集成JWT
文章目录 JWT简介在Django中使用JWT1. 安装2. 配置3. 添加认证接口 客户端使用JWT1. 获取新token2. 调用API3. 刷新token 同步发布在个人站点:https://panzhixiang.cn JWT简介 JWT(JSON Web Token)是一种流行的跨域认证解决方案。它可以在令牌中安全地传输用户身份…...
hive进行base64 加密解密函数
加密 select base64(cast(abcd as binary))YWJjZA 解密 -- 直接解密(结果字段格式为比binary格式) select unbase64(YWJjZA) -- 格式转换 select cast(unbase64(YWJjZA) as string) abcd...
Docker安装GitLab及使用图文教程
作者: 宋发元 GitLab安装及使用教程 官方教程 https://docs.gitlab.com/ee/install/docker.html Docker安装GitLab 宿主机创建容器持久化目录卷 mkdir -p /docker/gitlab/{config,data,logs}拉取GitLab镜像 docker pull gitlab/gitlab-ce:15.3.1-ce.0运行GitLa…...
OpenClaw自动化测试:Qwen3.5-9B-AWQ-4bit驱动UI截图比对
OpenClaw自动化测试:Qwen3.5-9B-AWQ-4bit驱动UI截图比对 1. 为什么需要自动化UI测试 作为个人开发者,每次前端代码修改后最头疼的就是手动检查各个页面的UI变化。传统做法要么是人工逐页比对,要么依赖复杂的测试框架配置。直到我发现OpenCl…...
SEO_ 揭秘影响搜索引擎排名的核心SEO因素
SEO的核心因素解析:提升搜索引擎排名的关键路径 在当今数字化时代,搜索引擎优化(SEO)已经成为每个网站和企业获取有效流量的重要途径。究竟有哪些核心因素影响搜索引擎的排名呢?本文将深入探讨这些核心SEO因素&#x…...
Flink StateBackend详解:大数据状态存储方案
Flink StateBackend详解:大数据状态存储的底层逻辑与实践 关键词 Flink 流处理、StateBackend、状态存储、Checkpoint、Exactly-Once、RocksDB、FsStateBackend 摘要 在大数据实时计算领域,状态(State)是流处理从"无状态计算…...
如何高效利用孔祥仁线性代数网课?我的实战笔记与技巧分享
如何高效利用孔祥仁线性代数网课?我的实战笔记与技巧分享 线性代数作为数学领域的重要分支,在计算机科学、物理学、工程学等多个学科中都有广泛应用。对于许多学生来说,这门课程既抽象又充满挑战。孔祥仁老师的线性代数网课以其"零废话&…...
SonarQube实战:通过pom.xml配置sonar-maven-plugin实现自动化代码扫描
1. 为什么需要自动化代码扫描 在软件开发过程中,代码质量是决定项目成败的关键因素之一。想象一下,你正在建造一栋房子,如果砖块质量不过关,水泥配比不对,即使外观再漂亮,也可能随时倒塌。代码也是如此&…...
Wan 3D Causal VAE:一篇讲清视觉 token、时间压缩、3D Causal 卷积
从 Emu3.5、Show-o2、Show-o、Chameleon,到 Wan 3D Causal VAE:一篇讲清视觉 token、时间压缩、3D Causal 卷积和数据量估算的入门分析 0. 先说这篇文章要解决什么问题 这篇文章想回答 6 个问题: Emu3.5、Show-o2、Show-o、Chameleon 这几类 UMM,到底是怎么表示图像和视频…...
3步实现GitHub资源精准提取:开发者必备的效率工具
3步实现GitHub资源精准提取:开发者必备的效率工具 【免费下载链接】DownGit github 资源打包下载工具 项目地址: https://gitcode.com/gh_mirrors/dow/DownGit 你是否曾遇到这样的困境:急需从GitHub仓库中获取一个特定文件夹,却不得不…...
m4s-converter:重构B站缓存管理的格式转换解决方案
m4s-converter:重构B站缓存管理的格式转换解决方案 【免费下载链接】m4s-converter 一个跨平台小工具,将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter m4s-converter是一款开源工具&…...
ESP32 RMT硬件驱动RF遥控库:替代rc-switch的异步OOK方案
1. 项目概述RCSwitchRmt 是一款专为 ESP32 系列微控制器设计的射频(RF)OOK(On-Off Keying,开关键控)通信库,其核心目标是提供一种现代、异步、非阻塞的硬件驱动型替代方案,以取代广为人知但已显…...
PX4固件二次开发入门:从源码结构到第一个自定义模块(基于v1.11版本)
PX4固件二次开发实战:从源码解析到自定义模块开发(v1.11版本) 当你第一次打开PX4的源码仓库,面对数十个文件夹和数千个文件时,那种扑面而来的压迫感我深有体会。作为过来人,我想分享一套系统性的二次开发方…...
