大家好,我是欧阳方超,可以扫描下方二维码关注我的公众号“欧阳方超”,后续内容将在公众号首发。
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/9d49c49f0ed142f79fb70880a01e273e.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/01da15a449d04253a78441d822c908cb.jpeg)
1、概述
查询目录的无限层级树形结构是一个常见的需求,比如文件管理器、网盘、公司组织机构等场景。实现这种结构需要递归遍历目录,并将目录信息组织成树形结构。这篇文章,记录了实现步骤和关键点。
2、定义表结构
假如有如下的表结构:
CREATE TABLE `t_organization` (
`id` int NOT NULL AUTO_INCREMENT,
`org_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '机构id',
`org_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '机构名称',
`p_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '上级结构id',
`superior` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '上级机构',
`is_valid` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '是' COMMENT '是否有效',
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '描述',
`update_user` int DEFAULT NULL COMMENT '记录更新用户',
`update_time` bigint DEFAULT NULL COMMENT '记录更新时间',
`display_order` int NOT NULL DEFAULT '0' COMMENT '显示顺序',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='组织机构表';
3、Java实现
下面的代码实现了查询组织的层级结构。
/**
* 以树形结构查询组织机构
*/
public List<OrganizationVO>getOrgList() {
LambdaQueryWrapper<Organization> organizationLambdaQueryWrapper = new LambdaQueryWrapper<>();
organizationLambdaQueryWrapper.eq(Organization::getIsValid, isValid);
List<Organization> rootOrgList = this.list(organizationLambdaQueryWrapper);
List<OrganizationVO> organizationVOlist = new ArrayList<>();
for (Organization temp : CollectionUtils.emptyIfNull(rootOrgList)) {
OrganizationVO organizationVO = new OrganizationVO();
BeanUtils.copyProperties(temp, organizationVO);
organizationVOlist.add(organizationVO);
}
List<OrganizationVO> organizationVOresultList = new ArrayList<>();
// 先找到所有的一级节点
organizationVOlist.forEach(node->{
int index = 1;
index += organizationVOlist.stream().filter(rootNode -> node.getPId().equals(rootNode.getOrgId())).count();
if(index == 1){ //如果没有与当前pId相等的orgId,则index仍然为1,意味着是一级节点,则将一级节点加入最后结果列表中
organizationVOresultList.add(node);
}
});
// 递归地为一级节点设置子节点
organizationVOresultList.forEach(node->node.setChildren(childHandle(node.getOrgId(), organizationVOlist)));
return organizationVOresultList;
}
//递归地获取子节点
private List<OrganizationVO> childHandle(String orgId, List<OrganizationVO> list) {
List<OrganizationVO> childList = new ArrayList<>();
// 遍历所有节点,如果该节点的父类id等于orgId,则作为子节点加入当前节点中
list.forEach(node->{
if (node.getPId().equals(orgId)) {
childList.add(node);
}
});
// 把子节点的孩子节点循环一遍
childList.forEach(node->node.setChildren(childHandle(node.getOrgId(), list)));
if (childList.size() == 0) { return null; }
return childList;
}
4、总结
这种方式的关键点包括:
定义组织机构实体类,包含树形结构所需的属性;
从数据源查询所有部门信息;
遍历部门列表,首先构建一级节点;
为一级节点设置子节点,在该过程中递归地获取子节点;
通过这种方式,可以灵活地构建组织机构的树形结构。
我是欧阳方超,把事情做好了自然就有兴趣了,如果你喜欢我的文章,欢迎点赞、转发、评论加关注。我们下次见。