技术标签: spring boot java mybatis Spring Boot 后端 MyBatis-Plus
1. 前 言
在实际的开发中,一些菜单页面需要返回的不是一张列表,而一个树形结构的数据;
近期项目中也有需要获取全国行政区划省-市-区县-乡镇的树状结构数据,现将自己加班学习的获取树的方法总结如下,可能有不足之处,心血来潮之作,也希望大家批评指正!
首先,先做一个简单的例子进行说明
2. 简 单 实 例
2.1 定义VO类
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(description = "用户信息-userVO")
public class UserVo {
@ApiModelProperty("id")
private Long id;
@ApiModelProperty("父ID")
private Long parentId;
@ApiModelProperty("名称")
private String name;
@ApiModelProperty("子节点")
private List<UserVo> children;
@ApiModelProperty(value = "是否有孩子结点的标志")
@JsonIgnore
private Boolean flag = false;
// 添加结点到孩子结点集合
public void addChildren(UserVo userVo) {
this.children.add(userVo);
}
// 设置有孩子结点
public void hasChildren() {
if (this.flag) {
return;
}
this.flag = true;
this.children = new ArrayList<>();
}
}
2.2 Controller
public List<UserVO> userList(){
List<UserVO> resultVO = userService.getUserList();
return resultVO;
}
2.3 Service
public List<UserVO> getUserList(){
//一次性查询所有数据
List<userVO> users = userMapper.userList();
//存储UserVO->返回树形结构
List<UserVO> result = new ArrayList<>();
// 构造树形结构
for (int i = 0; i < users.size(); i++) {
userVO parent = users.get(i);
// 如果是根节点,则添加至树形结果列表
if (StringUtils.isBlank(parent.getParentId()) || StringUtils.equals(parent.getId(), parent.getParentId())) {
result.add(parent);
}
for (int j = 0; j < users.size(); j++) {
userVO children = users.get(j);
// 判断children是否是parent的孩子节点
if (StringUtils.equals(parent.getId(), children.getParentId())) {
parent.hasChildren();
parent.addChildren(children);
}
}
}
return result;
}
2.4 Mapper
略
3. 获取全国行政区划省-市-区县-乡镇的树状结构数据
3.1 定义VO类
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(description = "CategoryTreeVO")
public class CategoryTreeVO {
@ApiModelProperty(value = "主键id")
private long id;
@ApiModelProperty(value = "父id")
private long parentId;
@ApiModelProperty(value = "子节点")
private List<CategoryTreeVO> children = new ArrayList<>();
/* 此处两个方法可以结合到一处 -> children = new ArrayList<>();
// 添加结点到孩子结点集合
public void addChildren(UserVo userVo) {
this.children.add(userVo);
}
// 设置有孩子结点
public void hasChildren() {
if (this.flag) {
return;
}
this.flag = true;
this.children = new ArrayList<>();
}*/
}
3.2 Controller
public List<CategoryTreeVO> CategoryTreeList(){
List<CategoryTreeVO> resultVO = areaTreeService.getCategoryTreeList();
return resultVO;
}
3.3 Service
public List<CategoryTreeVO> getCategoryTreeList() {
//一次性查询所有数据
List<CategoryTreeVO> list= categoryTreeMapper.getCategoryTreeList();
//存储树形结构
List<CategoryTreeVO> result = new ArrayList<>();
TreeUtil treeUtilNew = new TreeUtil();
result = treeUtilNew.build(list); //进行封装
return result; //返回树形结构
}
3.4 Mapper
略
3.5 TreeUtil的编写
public class TreeUtil {
/**
* 根据pid,构建树节点
*/
public static <T extends CategoryTreeVO> List<T> build(List<T> treeNodes, Integer pid) {
List<T> treeList = new ArrayList<>();
for(T treeNode : treeNodes) {
if (pid.equals(treeNode.getParentId())) {
treeList.add(findChildren(treeNodes, treeNode));
}
}
return treeList;
}
/**
* 查找子节点
*/
private static <T extends CategoryTreeVO> T findChildren(List<T> treeNodes, T rootNode) {
for(T treeNode : treeNodes) {
if(rootNode.getId().equals(treeNode.getParentId())) {
rootNode.getChildren().add(findChildren(treeNodes, treeNode));
}
}
return rootNode;
}
/**
* 构建树节点
*/
public static <T extends CategoryTreeVO> List<T> build(List<T> treeNodes) {
List<T> result = new ArrayList<>();
//list转map
Map<BigInteger, T> nodeMap = new LinkedHashMap<>(treeNodes.size());
for(T treeNode : treeNodes){
nodeMap.put(treeNode.getId(), treeNode);
}
for(T node : nodeMap.values()) {
T parent = nodeMap.get(node.getParentId());
if(parent != null && !(node.getId().equals(parent.getId()))){
parent.getChildren().add(node);
continue;
}
result.add(node);
}
return result;
}
}
总结
以上是我从最近的项目中学到的返回树形结构的方法
文章浏览阅读1k次,点赞28次,收藏22次。图像噪声是图像在摄取或传输时所受的随机信号干扰,是图像中各种妨碍人们对其信息接受的因素。很多时候将图像噪声看成是多维随机过程,因而描述噪声的方法完全可以借用随机过程的描述,即用其概率分布函数和概率密度分布函数。图像噪声是多种多样的,其性质也千差万别,所以了解噪声的分类是很有必要的。_图像噪音
文章浏览阅读1.3k次,点赞45次,收藏22次。关联容器是C++标准库的一部分,用于存储和管理具有键值对的数据元素。与顺序容器(如vector和list)不同,关联容器的主要特点是它们能够快速查找特定键的值。这是因为关联容器内部使用了高效的数据结构(如二叉树或哈希表)来组织数据。std::set:一个集合,包含唯一元素,按特定顺序排序。std::map:一个映射,包含键值对,其中键是唯一的。std::multiset和std::multimap:类似于set和map,但允许键的重复。_c++的关联容器
文章浏览阅读5.5w次,点赞30次,收藏144次。一:如何修改el-select下拉框中选项的样式,网上的方法一般有两种:1.找到下拉框的类名,写一个全局的样式。2.通过/deep/来修改.el-select-dropdown__item的样式内容3.通过popper-class设置的类名添加样式以上几种方式中,第二种和第三种是无法生效的,而第一种形式虽然可以,但是会造成样式污染,在打包上传到服务器的时候,其他地方的样式可能会因此发生改变。二:问题分析上图中显示的是当选中el-select的选项时页面的结构,选项的容器并不在挂载的div#ap_el-select hover
文章浏览阅读904次。cdh配置hive.exec.dynamic.partition.mode看图说话,我是用的server2,所以根据自己情况配置_cdh hive.exec.dynamic.partition.mode
文章浏览阅读813次。请问大牛们:在使用Matlab:错误使用 mprint (line 231) Wrong # rnames in mprint,怎么解决?程序如下:T=12;N=10;W=normw(W1);y=A(:,[23]);x=A(:,[17:22]);for t=1:Tt1=(t-1)*N+1;t2=t*N;wx(t1:t2,:)=W*x(t1:t2,:);endxconstant=ones(N*T,1..._matlab print报错
文章浏览阅读467次。public String substring(int beginIndex, int endIndex)返回一个新字符串,它是此字符串的一个子字符串。该子字符串从指定的 beginIndex 处开始,一直到索引 endIndex - 1 处的字符。因此,该子字符串的长度为 endIndex-beginIndex。示例: "ham_java substring的用法
文章浏览阅读7.3k次,点赞5次,收藏30次。信息系统安全技术知识梳理_信息系统的准确性,完整性,可靠性,稳定性
文章浏览阅读2k次。最近在做项目的时候发现,微服务使用feign相互之间调用时,存在session丢失的问题。例如,使用Feign调用某个远程API,这个远程API需要传递一个鉴权信息,我们可以把cookie里面的session信息放到Header里面,这个Header是动态的,跟你的HttpRequest相关,我们选择编写一个拦截器来实现Header的传递,也就是需要实现RequestInterceptor接口,具体代码如下:@Configuration @EnableFeignClients(basePackag_自动运行的feign丢失cookie
文章浏览阅读1k次。javascript复选框 标题:使用JavaScript动态添加带有复选框的表格行 作者:Vivek Kapile 电子邮件:已快照 语言:JavaScript 平台:ASP.net中JavaScript 技术:用于ASP.net 级别:初学者 介绍 此代码将为想要学习的初学者提供帮助,帮助他们了解如何通过JavaScript在表中动态创建复选框。 我已经介..._js动态向td添加复选框
文章浏览阅读1.7w次,点赞27次,收藏116次。文章目录一、安装node二、配置淘宝镜像三、配置 vscode(win10)四、全局安装脚手架五、创建项目一、安装node请在官网下载安装:https://nodejs.org/zh-cn/vscode 中 点击 ( ctrl + `) 调出终端输入指令node -v,能显示版本号,说明 node 已经装好了输入指令npm -v,能显示版本号,说明 npm 可以使用了点击链接查看图文教程https://blog.csdn.net/qq_45677671/article/detail_react vscode
文章浏览阅读743次。树状数组的一维和二维_树状数组两个操作
文章浏览阅读55次。为什么需要socket.io? node.js提供了高效的服务端运行环境,但是由于浏览器端对HTML5的支持不一,为了兼容所有浏览器,提供卓越的实时的用户体验,并且为程序员提供客户端与服务端一致的编程体验,于是socket.io诞生。 socket.io设计的目标是支持任何的浏览器,任何Mobile设备。目前支持主流的PC浏览器(IE,Safari,Chrome,..._/package-my/msg-html5/msg-html5?url=ht