首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 從資料庫表構建樹狀結構並輸出 JSON:完整實作指南

     編輯:Java 相關知識

組織架構、選單權限、分類目錄等業務場景常需將扁平化資料表(含 id、parentId、name)轉換為樹狀 JSON。本文提供基於 fastjson 的通用樹構建元件,包含資料模型 Tree<T>、建構器 BuildTree 與測試範例,可直接整合至專案。

一、應用場景與資料結構

典型資料表欄位:

  • code / id:節點唯一標識
  • pcode / parentId:父節點標識(根節點為空或 "0")
  • name / text:顯示文字

測試資料(21 筆,三層架構):

List<Test> tests = new ArrayList<>();
tests.add(new Test("0", "", "關於本人"));        // 根
tests.add(new Test("1", "0", "技術學習"));      // 1層
tests.add(new Test("2", "0", "興趣"));
tests.add(new Test("3", "1", "JAVA"));          // 2層
tests.add(new Test("4", "1", "oracle"));
tests.add(new Test("5", "1", "spring"));
tests.add(new Test("6", "1", "springmvc"));
tests.add(new Test("7", "1", "fastdfs"));
tests.add(new Test("8", "1", "linux"));
tests.add(new Test("9", "2", "騎行"));
tests.add(new Test("10", "2", "吃喝玩樂"));
tests.add(new Test("11", "2", "學習"));
tests.add(new Test("12", "3", "String"));       // 3層
tests.add(new Test("13", "4", "sql"));
tests.add(new Test("14", "5", "ioc"));
tests.add(new Test("15", "5", "aop"));
tests.add(new Test("16", "1", "等等"));
tests.add(new Test("17", "2", "等等"));
tests.add(new Test("18", "3", "等等"));
tests.add(new Test("19", "4", "等等"));
tests.add(new Test("20", "5", "等等"));

二、通用樹節點模型 Tree<T>

支援序列化為 JSON、攜帶任意業務屬性、狀態控制(展開/折疊、勾選):

public class Tree<T> {
    private String id;
    private String text;
    private String state = "open";      // open / closed
    private boolean checked = false;
    private List<Map<String, Object>> attributes; // 擴充屬性
    private List<Tree<T>> children = new ArrayList<>();
    
    private String parentId;
    private boolean isParent = false;   // 是否為父節點
    private boolean isChildren = false; // 是否有子節點

    // Getter/Setter 略...
    
    @Override
    public String toString() {
        return JSON.toJSONString(this); // fastjson 直接序列化
    }
}

三、樹構建核心演算法 BuildTree.build()

採用 雙層迴圈匹配 parentId,時間複雜度 O(n²),資料量 < 5000 時效能可接受;大資料量建議改用 Map<id, node> 優化至 O(n)。

public class BuildTree {
    public static <T> Tree<T> build(List<Tree<T>> nodes) {
        if (nodes == null) return null;
        
        List<Tree<T>> topNodes = new ArrayList<>();
        
        // 1. 找出所有頂層節點(parentId 為空)
        for (Tree<T> child : nodes) {
            String pid = child.getParentId();
            if (pid == null || pid.isEmpty()) {
                topNodes.add(child);
                continue;
            }
            // 2. 在節點列表中尋找父節點
            for (Tree<T> parent : nodes) {
                if (parent.getId() != null && parent.getId().equals(pid)) {
                    parent.getChildren().add(child);
                    child.setParent(true);
                    parent.setChildren(true);
                    break;
                }
            }
        }
        
        // 3. 建立虛擬根節點(若有多個頂層節點)
        Tree<T> root = new Tree<>();
        if (topNodes.size() == 1) {
            root = topNodes.get(0);
        } else {
            root.setId("-1");
            root.setText("頂級節點");
            root.setChecked(true);
            root.setChildren(topNodes);
            root.setChildren(true);
        }
        return root;
    }
}

四、測試驅動與 JSON 輸出

public class BuildTreeTester {
    public static void main(String[] args) {
        List<Tree<Test>> trees = new ArrayList<>();
        for (Test t : tests) {
            Tree<Test> node = new Tree<>();
            node.setId(t.getId());
            node.setParentId(t.getPid());
            node.setText(t.getText());
            trees.add(node);
        }
        
        Tree<Test> root = BuildTree.build(trees);
        System.out.println(root); // 輸出 JSON
    }
}

五、輸出 JSON 範例(格式化後)

{
  "id": "-1",
  "text": "頂級節點",
  "state": "open",
  "checked": true,
  "children": [
    {
      "id": "0",
      "text": "關於本人",
      "parentId": "",
      "parent": false,
      "children": [
        {
          "id": "1",
          "text": "技術學習",
          "parentId": "0",
          "parent": true,
          "children": [
            { "id": "3", "text": "JAVA", "children": [
                { "id": "12", "text": "String" },
                { "id": "18", "text": "等等" }
            ]},
            { "id": "4", "text": "oracle", "children": [
                { "id": "13", "text": "sql" },
                { "id": "19", "text": "等等" }
            ]},
            { "id": "5", "text": "spring", "children": [
                { "id": "14", "text": "ioc" },
                { "id": "15", "text": "aop" },
                { "id": "20", "text": "等等" }
            ]},
            { "id": "6", "text": "springmvc" },
            { "id": "7", "text": "fastdfs" },
            { "id": "8", "text": "linux" },
            { "id": "16", "text": "等等" }
          ]
        },
        {
          "id": "2",
          "text": "興趣",
          "parentId": "0",
          "parent": true,
          "children": [
            { "id": "9", "text": "騎行" },
            { "id": "10", "text": "吃喝玩樂" },
            { "id": "11", "text": "學習" },
            { "id": "17", "text": "等等" }
          ]
        }
      ]
    }
  ]
}

六、效能優化建議(大資料量)

// O(n) 版本:先建 Map<id, Tree>,再單層迴圈掛載
public static <T> Tree<T> buildOptimized(List<Tree<T>> nodes) {
    Map<String, Tree<T>> map = new HashMap<>();
    nodes.forEach(n -> map.put(n.getId(), n));
    
    Tree<T> root = new Tree<>();
    for (Tree<T> node : nodes) {
        String pid = node.getParentId();
        if (pid == null || pid.isEmpty() || !map.containsKey(pid)) {
            root.getChildren().add(node); // 視為頂層
        } else {
            map.get(pid).getChildren().add(node);
            map.get(pid).setChildren(true);
            node.setParent(true);
        }
    }
    return root.getChildren().size() == 1 ? root.getChildren().get(0) : root;
}

七、整合前端樹元件

輸出 JSON 符合 jQuery EasyUI Tree、zTree、Bootstrap Treeview 等主流前端樹元件格式,僅需調整欄位名稱(如 text→name、children→nodes)即可直接綁定。

原文出處:Java 根據資料庫表內容生成樹結構 JSON 資料

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved