在平时的开发工作中,经常遇到这样一个场景,在数据库中存储了具有父子关系的数据,需要将这些数据以树形结构的形式在界面上进行展示。本文的目的是提供了一个通用的编程模型,解决将具有父子关系的数据转换成树形结构的问题。如有不正之处,欢迎大家批评指正。

编程模型

我们以北京行政区划为例,讲解整个模型。

北京市:市辖区 县

市辖区:东城区 西城区 朝阳区 丰台区 石景山区 海淀区 门头沟区 房山区 通州区 顺义区 昌平区 大兴区 怀柔区 平谷区

县:密云县 延庆县

UML类图如下:

TreeNode:定义树的节点对象

  • nodeId:树节点Id。
  • nodeName:树节点名称。
  • parentNodeId:树节点父Id。
  • orderNum:节点在树中的排序号,在同一节点下进行排序。
  • level:当前树节点所在的层级,根节点为第一层。
  • parent:当前树节点的父节点。
  • children:当前树节点的儿子节点。
  • allChildren:当前树节点的子孙节点。

ITree:定义树对象要实现的方法。

  • getTree():以 List 形式返回树的所有的 TreeNode 对象。
  • getRoot():以 List 形式返回树的根节点,可能是一个或者多个。
  • getTreeNode(String nodeId):根据 nodeId 返回对应的 TreeNode 对象。

Tree:实现 ITree 接口,提供树的完整功能。

  • getTree():以 List 形式返回树的所有的 TreeNode 对象。
  • getRoot():以 List 形式返回树的根节点,可能是一个或者多个。
  • getTreeNode(String nodeId):根据 nodeId 返回对应的 TreeNode 对象。

ITreeNode:定义模板方法,构造树形结构的类要实现该接口,Tree 通过调用该接口中的方法获取 nodeId nodeName parentNodeId orderNum 数据。

  • getNodeId():获取树节点Id。
  • getNodeName():获取树节点名称。
  • getParentNodeId():获取树节点父Id。
  • getOrderNum():获取节点在树中的排序号,在同一节点下进行排序。

Org:定义行政区划类,实现 ItreeNode 接口。

实现代码

TreeNode类:

package com.ips.tree;import java.util.ArrayList;
import java.util.List;import com.alibaba.fastjson.annotation.JSONField;/*** <p>Title: 树节点</p>* <p>Description:一棵树由许多包含父子关系的节点组成 </p>* @author  liuzhibo* @date    2017年1月18日*/
public class TreeNode {//树节点ID@JSONField(ordinal=1)private String nodeId;//树节点名称@JSONField(ordinal=2)private String nodeName;//父节点ID@JSONField(ordinal=3)private String parentNodeId;//节点在树中的排序号@JSONField(ordinal=4)private int orderNum;//节点所在的层级@JSONField(ordinal=5)private int level;private TreeNode parent;//当前节点的二子节点@JSONField(ordinal=6)private List<TreeNode> children = new ArrayList<TreeNode>();//当前节点的子孙节点private List<TreeNode> allChildren = new ArrayList<TreeNode>();public TreeNode(ITreeNode obj){this.nodeId = obj.getNodeId();this.nodeName = obj.getNodeName();this.parentNodeId = obj.getNodeParentId();this.orderNum = obj.getOrderNum();}public void addChild(TreeNode treeNode){this.children.add(treeNode);}public void removeChild(TreeNode treeNode){this.children.remove(treeNode);}public String getNodeId() {return nodeId;}public void setNodeId(String nodeId) {this.nodeId = nodeId;}public String getNodeName() {return nodeName;}public void setNodeName(String nodeName) {this.nodeName = nodeName;}public String getParentNodeId() {return parentNodeId;}public void setParentNodeId(String parentNodeId) {this.parentNodeId = parentNodeId;}public int getLevel() {return level;}public void setLevel(int level) {this.level = level;}public TreeNode getParent() {return parent;}public void setParent(TreeNode parent) {this.parent = parent;}public List<TreeNode> getChildren() {return children;}public void setChildren(List<TreeNode> children) {this.children = children;}public int getOrderNum() {return orderNum;}public void setOrderNum(int orderNum) {this.orderNum = orderNum;}public List<TreeNode> getAllChildren() {if(this.allChildren.isEmpty()){for(TreeNode treeNode : this.children){this.allChildren.add(treeNode);this.allChildren.addAll(treeNode.getAllChildren());}}return this.allChildren;}
}

ITree接口:

package com.ips.tree;import java.util.List;public interface ITree {public List<TreeNode> getTree();public List<TreeNode> getRoot();public TreeNode getTreeNode(String nodeId);
}

Tree类:

package com.ips.tree;import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;public class Tree implements ITree {private HashMap<String, TreeNode> treeNodesMap = new HashMap<String, TreeNode>();private List<TreeNode> treeNodesList = new ArrayList<TreeNode>();public Tree(List<ITreeNode> list){initTreeNodeMap(list);initTreeNodeList();}private void initTreeNodeMap(List<ITreeNode> list){TreeNode treeNode = null;for(ITreeNode item : list){treeNode = new TreeNode(item);treeNodesMap.put(treeNode.getNodeId(), treeNode);}Iterator<TreeNode> iter = treeNodesMap.values().iterator();TreeNode parentTreeNode = null;while(iter.hasNext()){treeNode = iter.next();if(treeNode.getParentNodeId() == null || treeNode.getParentNodeId() == ""){continue;}parentTreeNode = treeNodesMap.get(treeNode.getParentNodeId());if(parentTreeNode != null){treeNode.setParent(parentTreeNode);parentTreeNode.addChild(treeNode);}}}private void initTreeNodeList(){if(treeNodesList.size() > 0){return;}if(treeNodesMap.size() == 0){return;}Iterator<TreeNode> iter = treeNodesMap.values().iterator();TreeNode treeNode = null;while(iter.hasNext()){treeNode = iter.next();if(treeNode.getParent() == null){this.treeNodesList.add(treeNode);this.treeNodesList.addAll(treeNode.getAllChildren());}}}@Overridepublic List<TreeNode> getTree() {return this.treeNodesList;}@Overridepublic List<TreeNode> getRoot() {List<TreeNode> rootList = new ArrayList<TreeNode>();if (this.treeNodesList.size() > 0) {for (TreeNode node : treeNodesList) {if (node.getParent() == null)rootList.add(node);}}return rootList;}@Overridepublic TreeNode getTreeNode(String nodeId) {return this.treeNodesMap.get(nodeId);}}

ITreeNode 接口:

package com.ips.tree;public interface ITreeNode {public String getNodeId();public String getNodeName();public String getNodeParentId();public Integer getOrderNum();
}

Org 类:

package com.ips.tree;public class Org implements ITreeNode {private String uuid;private String parentId;private String name;private Integer orderNum;private String code;private String type;public Org(){}public Org(String uuid, String parentId, String name, Integer orderNum, String code, String type){this.uuid = uuid;this.parentId = parentId;this.name = name;this.orderNum = orderNum;this.code = code;this.type = type;}@Overridepublic String getNodeId() {return this.uuid;}@Overridepublic String getNodeName() {return this.name;}@Overridepublic String getNodeParentId() {return this.parentId;}@Overridepublic Integer getOrderNum() {return this.orderNum;}public String getUuid() {return uuid;}public void setUuid(String uuid) {this.uuid = uuid;}public String getParentId() {return parentId;}public void setParentId(String parentId) {this.parentId = parentId;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getType() {return type;}public void setType(String type) {this.type = type;}public void setOrderNum(Integer orderNum) {this.orderNum = orderNum;}}

TreeDemo 类:执行该类的 main 方法,查看效果。

package com.ips.tree;import java.util.ArrayList;
import java.util.List;import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SimplePropertyPreFilter;public class TreeDemo {public static void main(String[] args) {Tree tree = new Tree(genOrgList());TreeNode treeNode = tree.getTreeNode("2");SimplePropertyPreFilter filter = new SimplePropertyPreFilter(); // 构造方法里,也可以直接传需要序列化的属性名字filter.getExcludes().add("parent");filter.getExcludes().add("allChildren");String data = JSONObject.toJSONString(treeNode, filter);System.out.println(data);}public static List<ITreeNode> genOrgList(){List<ITreeNode> list = new ArrayList<ITreeNode>();Org org = new Org("2", "1", "北京市", 2, "110000", "2");list.add(org);org = new Org("3", "2", "市辖区", 3, "110100", "3");list.add(org);org = new Org("4", "3", "东城区", 4, "110101", "4");list.add(org);org = new Org("5", "3", "东城区", 5, "110102", "4");list.add(org);org = new Org("6", "3", "东城区", 6, "110105", "4");list.add(org);org = new Org("7", "3", "东城区", 7, "110106", "4");list.add(org);org = new Org("8", "3", "东城区", 8, "110107", "4");list.add(org);org = new Org("9", "3", "东城区", 9, "110108", "4");list.add(org);org = new Org("10", "3", "东城区", 10, "110109", "4");list.add(org);org = new Org("11", "3", "东城区", 11, "110111", "4");list.add(org);org = new Org("12", "3", "东城区", 12, "110112", "4");list.add(org);org = new Org("13", "3", "东城区", 13, "110113", "4");list.add(org);org = new Org("14", "3", "东城区", 14, "110114", "4");list.add(org);org = new Org("15", "3", "东城区", 15, "110115", "4");list.add(org);org = new Org("16", "3", "东城区", 16, "110116", "4");list.add(org);org = new Org("17", "3", "东城区", 17, "110117", "4");list.add(org);org = new Org("18", "2", "县", 3, "110200", "3");list.add(org);org = new Org("19", "18", "密云县", 19, "110228", "4");list.add(org);org = new Org("20", "18", "延庆县", 20, "110229", "4");list.add(org);return list;}}

执行结果如下:

{"nodeId": "2","nodeName": "北京市","parentNodeId": "1","orderNum": 2,"level": 0,"children": [{"nodeId": "18","nodeName": "县","parentNodeId": "2","orderNum": 3,"level": 0,"children": [{"nodeId": "19","nodeName": "密云县","parentNodeId": "18","orderNum": 19,"level": 0,"children": []},{"nodeId": "20","nodeName": "延庆县","parentNodeId": "18","orderNum": 20,"level": 0,"children": []}]},{"nodeId": "3","nodeName": "市辖区","parentNodeId": "2","orderNum": 3,"level": 0,"children": [{"nodeId": "17","nodeName": "东城区","parentNodeId": "3","orderNum": 17,"level": 0,"children": []},{"nodeId": "15","nodeName": "东城区","parentNodeId": "3","orderNum": 15,"level": 0,"children": []},{"nodeId": "16","nodeName": "东城区","parentNodeId": "3","orderNum": 16,"level": 0,"children": []},{"nodeId": "13","nodeName": "东城区","parentNodeId": "3","orderNum": 13,"level": 0,"children": []},{"nodeId": "14","nodeName": "东城区","parentNodeId": "3","orderNum": 14,"level": 0,"children": []},{"nodeId": "11","nodeName": "东城区","parentNodeId": "3","orderNum": 11,"level": 0,"children": []},{"nodeId": "12","nodeName": "东城区","parentNodeId": "3","orderNum": 12,"level": 0,"children": []},{"nodeId": "10","nodeName": "东城区","parentNodeId": "3","orderNum": 10,"level": 0,"children": []},{"nodeId": "7","nodeName": "东城区","parentNodeId": "3","orderNum": 7,"level": 0,"children": []},{"nodeId": "6","nodeName": "东城区","parentNodeId": "3","orderNum": 6,"level": 0,"children": []},{"nodeId": "5","nodeName": "东城区","parentNodeId": "3","orderNum": 5,"level": 0,"children": []},{"nodeId": "4","nodeName": "东城区","parentNodeId": "3","orderNum": 4,"level": 0,"children": []},{"nodeId": "9","nodeName": "东城区","parentNodeId": "3","orderNum": 9,"level": 0,"children": []},{"nodeId": "8","nodeName": "东城区","parentNodeId": "3","orderNum": 8,"level": 0,"children": []}]}]
}

注:该示例中使用了 alibaba 的 fastjson 实现类对象序列化,maven 依赖如下:

<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.20</version>
</dependency>

Java编程:将具有父子关系的数据库表数据转换为树形结构,支持无限层级相关推荐

  1. java父子表_Java编程:将具有父子关系的数据库表数据转换为树形结构,支持无限层级...

    在平时的开发工作中,经常遇到这样一个场景,在数据库中存储了具有父子关系的数据,需要将这些数据以树形结构的形式在界面上进行展示.本文的目的是提供了一个通用的编程模型,解决将具有父子关系的数据转换成树形结 ...

  2. python画父子关系图_将有父子关系的一维数组转换成树形结构(多维)数据

    先来个函数注释 : /** * 将有父子关系的一维数组转换成树形结构(多维)数据 * console.log(JSON.stringify(setTreeData(data), null, 2)); ...

  3. mysql 父子维,将有父子关系的一维数组转换成树形结构(多维)数据

    拉莫斯之舞 先来个函数注释 :/** * 将有父子关系的一维数组转换成树形结构(多维)数据 * console.log(JSON.stringify(setTreeData(data), null,  ...

  4. 帆软报表列表_帆软报表(finereport)读取数据库表数据生成报表

    帆软报表(finereport)读取数据库表数据生成报表 发布时间:2019-01-14 16:48, 浏览次数:856 , 标签: finereport 1.首先是安装帆软报表软件,微软的傻瓜式安装 ...

  5. 导出远程mysql数据库中的表_shell脚本实现导出远程mysql数据库表数据至本地

    bin/main.sh脚本内容 #!/bin/bash #作用:用于同步远程mysql数据库表数据至本地 #作者:丁艺博 source /etc/profile source ~/.bash_prof ...

  6. python提取数据库数据_Python如何读取MySQL数据库表数据

    本文实例为大家分享了Python读取MySQL数据库表数据的具体代码,供大家参考,具体内容如下 环境:Python 3.6 ,Window 64bit 目的:从MySQL数据库读取目标表数据,并处理 ...

  7. mysql数据库实验查询_MySQL数据库表数据的查询操作实验

    实验3.MySQL数据库表数据的查询操作实验(1) 一.实验目的 掌握SELECT 语句的基本语法格式. 掌握SELECT 语句的执行方法. 掌握SELECT 语句的 GROUP BY 和 ORDER ...

  8. MySQL快速比较数据库表数据

    1. 前言 有时需要比较MySQL不同数据库间结构相同的表数据是否相同,例如在测试环境与生产环境之间比较,或多个测试环境之间比较,以下提供一种通用的快速比较方式. 2. 比较方法 对于需要比较数据的数 ...

  9. 读取ACCESS数据库表数据

    Sub 读取数据库表数据()Dim cnn As New Connection, rs As New RecordsetDim strSql As String, i As Long, Sh As W ...

  10. sql server 触发器实时同步数据库表数据

    sql server 触发器实时同步数据库表数据 创建两个相同结构的数据库表 CREATE TABLE [dbo].[Table_1]([id] [varchar](50) NOT NULL,[nam ...

最新文章

  1. JAVA 和.NET在安全功能的比较
  2. Google 的开源技术protobuf 简介与例子
  3. eclipse plugin 菜单
  4. 前端学习(2843):UI插件开发
  5. koa2 mysql 中间件_Koa2 和 Express 中间件对比
  6. 浅谈三层架构 通过这个,+Java开发模式经验。终于相通了,动软到底是为什么这么做...
  7. ubuntu下screen的使用
  8. cad经典工作空间_最实用的CAD界面的设置
  9. android将手机能当蓝牙耳机使用吗,如何将Android手机作为蓝牙耳机?
  10. python进行谱曲_人工智能可以作曲吗?
  11. 计算机无法关机和重启怎么办,关于电脑无法关机怎么办
  12. 做小红书推广快速涨粉的技巧_云媒易
  13. Php绘制棋盘,第二次DIY棋盘,纯手工绘制完美棋盘
  14. LeetCode-86
  15. 拾忆Elasticsearch03:SpringBoot整合 Elasticsearch
  16. 聊聊Dubbo3.0新特性之应用级服务发现
  17. 阿里 oracle 时间戳,阿里巴巴的骄傲,合伙人刘振飞回忆,OceanBase十年时间登上巅峰...
  18. windows安全警报怎么关闭_永久关闭WIN10自动杀毒(windows安全中心)
  19. 抖音视频批量发布方法
  20. js 中文转为首字母拼音

热门文章

  1. Windows 禁用U盘的程序,不用注册表方式。
  2. 怎样在服务器上运行ea,外汇EA如何在MT4上运行?以及如何挂到服务器?
  3. 查看计算机配置在哪里,怎么看电脑配置 查看电脑配置的方法有哪些
  4. Python的request库爬取豆瓣电影排行
  5. 解决谷歌浏览器被篡改主页问题
  6. 一篇文章完全搞懂正则化(Regularization)
  7. 【100+ python基础入门-42】Python函数参数的六种类型
  8. 25年前,开发者如何将游戏塞进内存?
  9. STM32 CAN通讯过滤器使用总结及代码分析
  10. 免费的IT类技术书籍大全