
文章目錄數據庫組裝樹如果某個節點缺失如何判斷呢?如何遷移?授權時的樹和查詢時是不一樣的樹結構很常見例如組織結構菜單等所以必須會套路。數據庫至少要包含以下幾個主要字段idparent_idlevel # 層級leaf_flag # 是否葉子節點CREATETABLEsys_tree_node(idbigint(20)NOTNULLAUTO_INCREMENTCOMMENT主鍵ID,parent_idbigint(20)DEFAULT0COMMENT父節點ID根節點默認為0,ancestorsvarchar(500)DEFAULTCOMMENT祖級列表例如0,100,200,node_namevarchar(100)NOTNULLCOMMENT節點名稱,node_codevarchar(100)DEFAULTCOMMENT節點編碼用于業務關聯如部門編碼、菜單標識,node_typetinyint(4)DEFAULT1COMMENT節點類型如1-公司, 2-部門, 3-崗位,levelint(11)DEFAULT1COMMENT層級深度根節點為1,leaf_flagtinyint(1)DEFAULT0COMMENT是否葉子節點0-否, 1-是,sort_orderint(11)DEFAULT0COMMENT顯示排序,statustinyint(4)DEFAULT1COMMENT狀態0-停用, 1-正常,del_flagtinyint(1)DEFAULT0COMMENT刪除標志0-正常, 1-已刪除,create_byvarchar(64)DEFAULTCOMMENT創建者,create_timedatetimeDEFAULTCURRENT_TIMESTAMPCOMMENT創建時間,update_byvarchar(64)DEFAULTCOMMENT更新者,update_timedatetimeDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMPCOMMENT更新時間,remarkvarchar(500)DEFAULTNULLCOMMENT備注,PRIMARYKEY(id),KEYidx_parent_id(parent_id),KEYidx_ancestors(ancestors))ENGINEInnoDBDEFAULTCHARSETutf8mb4COMMENT通用樹結構表;組裝樹有各種方法例如層推法等等。比較好的是所有節點放到一個map里然后快速遍歷。代碼publicListTreeNodebuildTree(ListTreeNodeflatList){// 1. 將扁平列表轉為 MapKey 為節點 ID實現 O(1) 查找MapLong,TreeNodenodeMapflatList.stream().collect(Collectors.toMap(TreeNode::getId,node-node));ListTreeNoderootsnewArrayList();// 2. 遍歷組裝找到每個節點的父節點并掛載上去for(TreeNodenode:flatList){if(node.getParentId()null||node.getParentId()0){// 頂級節點根節點直接加入結果集roots.add(node);}else{// 非根節點通過 Map 快速找到父節點并加入其 children 列表TreeNodeparentnodeMap.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公司level3現在level2那么所有子節點的level1。A公司及所有子節點查出來level1后批量入庫即可速度很快。授權時的樹和查詢時是不一樣的授權時是整個樹結構(不能只展示已授權機構否則怎么加權限)通過復選框實現授權和取消授權。查詢時可以采用平面結構判斷起來更方便。