文章目录
- 数据库
- 组装树
- 如果某个节点缺失如何判断呢?
- 如何迁移?
- 授权时的树和查询时是不一样的
树结构很常见,例如组织结构,菜单等,所以必须会套路。
数据库
至少要包含以下几个主要字段:
id
parent_id
level # 层级
leaf_flag # 是否叶子节点
CREATETABLEsys_tree_node(idbigint(20)NOTNULLAUTO_INCREMENTCOMMENT'主键ID',parent_idbigint(20)DEFAULT'0'COMMENT'父节点ID(根节点默认为0)',ancestorsvarchar(500)DEFAULT''COMMENT'祖级列表(例如:0,100,200)',node_namevarchar(100)NOTNULLCOMMENT'节点名称',node_codevarchar(100)DEFAULT''COMMENT'节点编码(用于业务关联,如部门编码、菜单标识)',node_typetinyint(4)DEFAULT'1'COMMENT'节点类型(如:1-公司, 2-部门, 3-岗位)',levelint(11)DEFAULT'1'COMMENT'层级深度(根节点为1)',leaf_flagtinyint(1)DEFAULT'0'COMMENT'是否叶子节点(0-否, 1-是)',sort_orderint(11)DEFAULT'0'COMMENT'显示排序',statustinyint(4)DEFAULT'1'COMMENT'状态(0-停用, 1-正常)',del_flagtinyint(1)DEFAULT'0'COMMENT'删除标志(0-正常, 1-已删除)',create_byvarchar(64)DEFAULT''COMMENT'创建者',create_timedatetimeDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间',update_byvarchar(64)DEFAULT''COMMENT'更新者',update_timedatetimeDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMPCOMMENT'更新时间',remarkvarchar(500)DEFAULTNULLCOMMENT'备注',PRIMARYKEY(id),KEYidx_parent_id(parent_id),KEYidx_ancestors(ancestors))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COMMENT='通用树结构表';组装树
有各种方法,例如层推法等等。
比较好的是所有节点放到一个map里,然后快速遍历。代码:
publicList<TreeNode>buildTree(List<TreeNode>flatList){// 1. 将扁平列表转为 Map,Key 为节点 ID,实现 O(1) 查找Map<Long,TreeNode>nodeMap=flatList.stream().collect(Collectors.toMap(TreeNode::getId,node->node));List<TreeNode>roots=newArrayList<>();// 2. 遍历组装:找到每个节点的父节点,并挂载上去for(TreeNodenode:flatList){if(node.getParentId()==null||node.getParentId()==0){// 顶级节点(根节点)直接加入结果集roots.add(node);}else{// 非根节点,通过 Map 快速找到父节点并加入其 children 列表TreeNodeparent=nodeMap.get(node.getParentId());if(parent!=null){parent.getChildren().add(node);}}}returnroots;}这种写法不仅时间复杂度仅为 O(n),而且代码逻辑非常清晰。
如果某个节点缺失如何判断呢?
分不同情况,例如某个叶子节点缺失,那确实发现不了。
如果某个上级节点缺失,容易发现,如果node有parentId,但是没在map中,也没在数据库中,那可以报错该节点找不到上级节点。
如何迁移?
例如A公司下有3层100个公司,迁移到另外一个中心,要做什么?
方案很明确:
1、只需要修改A公司的parentId,因为其他子节点的parentId不变。
2、level也需要刷新,但是要用优雅的方式,先计算层级差,例如原来A公司level=3,现在level=2,那么所有子节点的level+1。A公司及所有子节点查出来,level+1后批量入库即可,速度很快。
授权时的树和查询时是不一样的
授权时是整个树结构(不能只展示已授权机构,否则怎么加权限),通过复选框实现授权和取消授权。
查询时可以采用平面结构,判断起来更方便。