数据库中的树形结构 - JAVA 设计 (通用)

java工程积累——树形结构的操作 通过这几天的观察,我们发现,集体的智慧永远是最强大的,每个人贡献一点点,我们就能将问题的解决方案在设计之初就升级到一个客观的程度,包括这次的树形结构的研究,相信你的队友不论他在你心理到底是什么状态,他既然被招进公司,肯定有他的闪光点打动了人力部门,且还有一句话,高手在民间,这句话,已经多次被验证了! 子段:i 阅读详情
我们通常会在应用中碰到树形结构的内容,比如 文件夹/文件模型, 部门组织结构,目录树等等,通常在设计模式中叫做 compose 模式。

在数据库中常常这样表示: 我们以Catalog (分级目录) 为例子

Catalog (分级目录)

字段名称

字段

类型

备注

目录ID

catalog_id

varchar(36)

pk, not null

目录名称

catalog_name

varchar(50)

not null

父目录ID

parent_id

varchar(36)

fk

创建时间

create_datetime

datetime

not null

目录描述

description

varchar(200)

 


我们考虑在数据库中一次将所有数据读入内存,然后在内存中生成一个Tree,这样可以减少数据库的访问,增加性能,并且只有的数据方式改变的时候,全部重新从数据库中生成Tree,否则一直保持在内存中。

我们使用标准的DAO模式先生成 POJO类(Catalog)和DAO类(CatalogDAO)。

然后我们建立相对通用的 Tree 和 TreeNode 类。

Tree.java

package com.humpic.helper.tree;

import java.util.*;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public abstract class Tree {
    
protected static Log log = LogFactory.getLog(Tree.class);

    
private Map treeNodeMaps = new Hashtable();
    
private TreeNode root;

    
/**
     * root if it's parent is empty
     
*/
    
protected void reload(List nodes) {
        log.info(
"tree will start reload all data");
        
        
synchronized (this) {
            
// initialize
            treeNodeMaps.clear();
            root 
= null;

            List treeNodes 
= new Vector(nodes.size());
            
for (int i = 0; i < nodes.size(); i++) {
                TreeNode node 
= this.transform(nodes.get(i)); // transform
                treeNodes.add(node);
                node.setTree(
this);
                treeNodeMaps.put(node.getNodeId(), node);
            }
            
            
for (int i = 0; i < treeNodes.size(); i++) {
                TreeNode node 
= (TreeNode) treeNodes.get(i);
                String parentId 
= node.getParentId();
                
if (this.isRootNode(node)) {
                    if (root == null) {
                        root 
= node;
                    } 
else {
                        log.error(
"find more then one root node. ignore.");
                    }

                } 
else {
                    
TreeNode parent = (TreeNode) treeNodeMaps.get(parentId);
                    
if (parent != null) {
                        parent.addChild(node);
                        node.setParent(parent);
                    } 
else {
                        log.warn(
"node [id=" + node.getNodeId() + "]: missing parent node.");
                    }

                }
            }
        }

        
if (root == null) {
            log.error(
"the root node is not be defined");
        }
    }

    protected boolean isRootNode(TreeNode node) {
        
return StringUtils.isBlank(node.getParentId());
    }

    public TreeNode getRootNode() {
        
return root;
    }

    
public TreeNode getTreeNode(String nodeId) {
        
return (TreeNode) treeNodeMaps.get(nodeId);
    }

    
public void addTreeNode(TreeNode node) {
        
synchronized (this) {
            treeNodeMaps.put(node.getNodeId(), node);

            String parentId 
= node.getParentId();
            
if (StringUtils.isNotBlank(parentId)) {
                TreeNode parent 
= getTreeNode(parentId);
                
if (parent != null) {
                    parent.addChild(node);
                    node.setParent(parent);
                } 
else {
                    log.error(
"parent cannot be found: " + node.getParentId());
                }
            } 
else {
                
if (root == null) {
                    root 
= node;
                } 
else {
                    log.error(
"find more then one root node. ignore.");
                }
            }
        }
    }

    
public void deleteTreeNode(String nodeId) {
        
synchronized (this) {
            TreeNode node 
= getTreeNode(nodeId);
            
if (node == null)
                
throw new IllegalArgumentException(nodeId + " cannot be found.");

            
if (node.getParent() == null) {
                root 
= null;
                treeNodeMaps.clear();
                log.warn(
"the root node has been removed.");
            } 
else {
                node.getParent().getChildren().remove(node);

                treeNodeMaps.remove(nodeId);
                List children 
= node.getAllChildren();
                
for (int i = 0; i < children.size(); i++) {
                    TreeNode n 
= (TreeNode) children.get(i);
                    treeNodeMaps.remove(n.getNodeId());
                }
            }
        }
    }

    
/**
     * <pre>
     * Usage: Office -&gt;
     * 
     * public TreeNode transform(Object info) {
     *     OfficeInfo office_info = (OfficeInfo) info;
     *     TreeNode node = new TreeNode();
     *     node.setNodeId(office_info.getOfficeId());
     *     node.setParentId(office_info.getParentId());
     *     node.setBindData(office_info);
     *     return node;
     * }
     * </pre>
     
*/
    
protected abstract TreeNode transform(Object info);
}

TreeNode.java

package com.humpic.helper.tree;

import java.util.List;
import java.util.Vector;

import org.apache.commons.collections.Predicate;
import org.apache.commons.lang.ObjectUtils;

public class TreeNode {

    
private Tree tree;
    
private TreeNode parent;
    
private List children = new Vector();
    
private List childrenGroup = new Vector();
    
private String nodeId;
    
private String parentId;
    
private Object bindData;

    
public String getNodeId() {
        
return nodeId;
    }

    
public void setNodeId(String nodeId) {
        
this.nodeId = nodeId;
    }

    
public String getParentId() {
        
return parentId;
    }

    
public void setParentId(String parentId) {
        
this.parentId = parentId;
    }

    
public Object getBindData() {
        
return bindData;
    }

    
public void setBindData(Object bindData) {
        
this.bindData = bindData;
    }

    
public Tree getTree() {
        
return tree;
    }

    
public void setTree(Tree tree) {
        
this.tree = tree;
    }

    
public void setParent(TreeNode parent) {
        
this.parent = parent;
    }

    
public TreeNode getParent() {
        
return this.parent;
    }

    
public List getChildren() {
        
return this.children;
    }

    
public void addChild(TreeNode node) {
        children.add(node);
    }

    
/**
     * get all children, and chilren's children
     
*/
    
public List getAllChildren() {
        
if (this.childrenGroup.isEmpty()) {
            
synchronized (this.tree) {
                
for (int i = 0; i < this.children.size(); i++) {
                    TreeNode node 
= (TreeNode) this.children.get(i);
                    
this.childrenGroup.add(node);
                    
this.childrenGroup.addAll(node.getAllChildren());
                }
            }
        }
        
return this.childrenGroup;
    }

    
/**
     * get all children, and chilren's children
     
*/
   
 public List getAllChildren(Predicate predicate) {
        List groups 
= new Vector();
        fillAllChildren(groups, predicate);
        
return groups;
    }

    
private void fillAllChildren(List groups, Predicate predicate) {
        
for (int i = 0; i < this.children.size(); i++) {
            TreeNode node 
= (TreeNode) this.children.get(i);
            
if (predicate.evaluate(node)) {
                groups.add(node);
                node.fillAllChildren(groups, predicate);
            }
        }
    }

    /**
     * get all parents, and parent's parent
     */

   
public List getParents() {
        List results =
new Vector();
        TreeNode parent =
this.getParent();
       
while (parent != null) {
            results.add(parent);
            parent = parent.getParent();
        }
       
return results;
    }

    
/**
     * A.isMyParent(B) == B is A' parent ? <br>
     * root.isMyParent(null) == true; <br>
     * root.isMyParent(*) == false <br>
     * *.isMyParent(null) == false
     
*/
    
public boolean isMyParent(String nodeId) {
        TreeNode target 
= tree.getTreeNode(nodeId);
        TreeNode parent 
= this.getParent();
        
if (parent == null) {
            
return target == null;
        } 
else {
            
return parent.equals(target);
        }
    }

    
/**
     * A.isMyAncestor(B) == B is A' ancestor ? <br>
     * *.isMyAncestor(null) == true;
     
*/
    
public boolean isMyAncestor(String nodeId) {
        TreeNode target 
= tree.getTreeNode(nodeId);
        
if (target == null)
            
return true;

        
return target.getAllChildren().contains(this);
    }

    
/**
     * A.isMyBrother(B) == B is A' brother ? <br>
     * *.isMyBrother(null) == false
     
*/
    
public boolean isMyBrother(String nodeId) {
        TreeNode target 
= tree.getTreeNode(nodeId);
        
if (target == null)
            
return false;

        TreeNode p1 
= this.getParent();
        TreeNode p2 
= target.getParent();
        
return ObjectUtils.equals(p1, p2);
    }

}

然后建立业务 Tree

CatalogTree.java

package com.humpic.helper.tree;

import java.util.List;
import org.apache.commons.collections.Predicate;

public class CatalogTree extends Tree {
    
private static CatalogTree instance = null;

    
private CatalogTree() {}
    
    
public static synchronized CatalogTree getInstance() {
        
if (instance == null) {
            instance = new CatalogTree();
            instance.reloadCatalogs();
        }
        
return instance;
    }

    
protected TreeNode transform(Object info) {
        Catalog catalog 
= (Catalog) info;
        TreeNode node 
= new TreeNode();
        node.setNodeId(catalog.getCatalogId());
        node.setParentId(catalog.getParentId());
        node.setBindData(catalog);
        
return node;
    }

    
public void reloadCatalogs() {
        List nodes 
= CatalogDAO.getInstance().findAll();
        
super.reload(nodes);
    }

    
public Catalog getCatalogNode(String catalogId) {
        TreeNode node 
= super.getTreeNode(catalogId);
        
return node == null ? null : (Catalog) node.getBindData();
    }
}

最后,我们只要使用以下的语句就可以了:

1. CatalogTree.getInstance().getTreeNode(...)
2. CatalogTree.getInstance().getCatalogNode(...)
3. CatalogTree.getInstance().getRootNode()

然后通过 TreeNode,就可以得到 parent, parents 和 children, allChildren

 

java 处理树形结构数据 阅读详情

相关推荐

数据库记录转树形结构的Java实现

层次结构数据是一种特殊的数据组织形式,它模仿了自然界和社会组织中的等级制度,如家庭族谱、组织架构图、文件目录等。在这种数据结构中,每个数据节点都有一个或多个“子节点”和一个“父节点”,形成了一种树形或倒立的树形结构。在树形结构中,顶层的节点称为根节点,根节点之下是各级子节点,子节点也可能有自己的子节点,以此类推。层次结构数据的特性包括:单根性:整个结构存在且只存在一个根节点。层次性:节点之间存在清晰的层级关系,数据从上层流向下层。唯一性。

weixin_33660045的博客 1103

MySQL系列(10)--数据库树形结构基础

树形结构 在了解索引之前先了解各种树形结构的区别,因为数据库所以系统都是基于树形结构设计的。 由上图看得出树是一些节点的集合,总结一下树的一些基本概念: 1、结点:树中的数据元素都称之为结点 2、根:最上面的结点称之为根,一颗树只有一个根且由根发展而来,从另外一个角度来说,每个结点都可以认为是其子树的根 3、父亲:结点的上层结点,如图中,结点K的父亲是E、结点L的父亲是G 4、兄弟:具有...

duanxiaobin的博客 1524

Tessent MBIST SDC

主要是两个PROC,tessent_constrain_${design_name}_mentor_ijtag_non_modal和tessent_constrain_${design_name}_mentor_memory_bist_modal。其中,Memory/MBIST controller/MEM Interface可以从func_clk_1来(用func_clk_1和func_clk_2的高频时钟),如图中红色线。其中,SIB和BAP用ijtag_tck的clock,如图绿色线。

po_poo的博客 1988

Java中树形(层次)结构数据库MySql设计方案(类似目录)

Java目录(层次)结构在数据库中如何去设计

weixin_44130574的博客 2629

ESP32-S3 + TB6600驱动42步进电机:从基础接线到AccelStepper库平滑加减速实战

本文详细介绍了如何使用ESP32-S3开发板和TB6600驱动器控制42步进电机,从基础接线到利用AccelStepper库实现平滑加减速控制。内容涵盖硬件连接、基础驱动代码、AccelStepper库的安装与参数调优,以及高级技巧与故障排除,帮助创客实现工业级精准控制。

weixin_42632434的博客 284

DPABI安装教程

DPABI是是中科院心理研究所严超赣老师团队开发的一款磁共振脑影像数据分析工具包。基于SPM,在安装DPABI之前需要安装好SPM,才能正常使用。SPM的安装方法见文matlab2021a版本条件下安装spm_kidllll的博客-优快云博客 1、下载安装包 下载地址:DPABI: a toolbox for Data Processing & Analysis for Brain Imaging | The R-fMRI Network 2、将下载好的dpabi文件夹移动到matl..

qq_42356925的博客 1万+

关系型数据库树形结构的设计

在进行程序设计的时候,树形结构常常被用来表征某些数据的关联关系,如企业上下级部门、商品分类、文件目录等等。这些树状结构需要借助于数据库完成持久化,而关系型数据库并没有对应的原生数据结构去存储查询这种数据结构,因此,设计一种合适的结构进行存储与查询是实现树状结构长久化存储的关键。

xinyu的记录博客 2823

【大数据Java基础-Java基础01】环境搭建(一)Sublime Text3搭建Java编译环境(Windows系统)

1. 首先配置好Java环境变量 我的jdk版本是1.8.0_191,存放目录是C:\Program Files\Java,因此添加以下环境变量 (1)系统变量→新建 JAVA_HOME 变量,变量值为: C:\Program Files\Java\jdk1.8.0_191 (2)系统变量→找到 Path 变量→编辑,末尾加入: ;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin 如果Path变量末尾本身有“;”,则上述路径前面则不需要加“;” (3)系统变量→新建 CL

微信搜:import_bigdata,大数据领域硬核原创作者 554

如何设计树形结构

我以前接触过一个前端插件,叫zTree。这个插件的作用是把接口返回的数据以树形结构的形式展示出来:--1.准备一个Div,设置id-->// 2.需要的数据name:"父节点1 - 展开",open:true,name:"父节点11 - 折叠",{ name:"叶子节点111"},{ name:"叶子节点112"},{ name:"叶子节点113"},{ name:"叶子节点114"}},name:"父节点12 - 折叠",{ name:"叶子节点121"},

smart_an的专栏 2290

SAP BOM批量反查代码分享

SAP BOM反查批量查询代码分享

我小时候很黑的博客 4972

virtuoso如何导出def?

在DEF Out界面,填写def name,library name以及cell name ,cell view既layout,把Output "Floating Shapes" into SPECIAL NETS Section勾上,OK即可。2)在要导出的layout界面选中PAD和prBoundary(shift+左键),快捷键C copy到空cell里,这时需要调整copy过来的object坐标,让两边prBoundary的坐标相同。我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧?

m0_61544122的博客 2307

数据库基础之树形查询结构设计

树形数据结构是我们常见的一种数据结构,比如文件目录、公司组织结构等。但是关系型数据库却没有对应的原生数据结构去存储查询这种数据结构,本文介绍了几种实现关系型数据库树形数据存储的方式供大家参考。 前言 树形结构是生活中常见的数据结构之一,如公司的组织结构、计算机文件的目录结构和家庭族谱等。本文将以区域作为示例,介绍几种常见的数据库实现树形查询的方式: 树形结构的关键属性:深度 方案一、毗邻目录模式(adjacency list model) 方案原理 毗邻目录模式在树形结构数据的每条记录中,记录了指向父数据

小明的博客 1153

C#与倍福Plc通信——使用仿真软件模拟倍福PLC运行

安装这个软件之前先安装VisualStudio,本文安装这个软件时已经安装了VisualStudio2019。1、下载倍福PLC编程软件TwinCAT。

qq_34059233的博客 3664

放入Java树_[导入][转]数据库中的树形结构 - JAVA 设计(通用)

packagecom.humpic.helper.tree;importjava.util.List;importjava.util.Vector;importorg.apache.commons.collections.Predicate;importorg.apache.commons.lang.ObjectUtils;publicclassTreeNode {privateTree tree...

weixin_28903391的博客 524

Sigrity SystemSI仿真分析教程文件路径

为了方便读者能够快速上手和学会Sigrity SystemSI 的功能,将Sigrity SystemSI仿真分析教程专栏所有文章对应的实例文件上传至以下路径。

weixin_54787054的博客 710

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Java通用树形结构数据封装

Java通用树形结构数据封装文章描述思路代码一, 树形实体类二,封装数据三,效果 文章描述 项目中经常使用到树形列表,树形结构数据都从服务器中拿取,服务器通过特定规则查询数据库封装树形结构数据,此时就需要考虑怎样写出一个最通用的方法封装数据。本人觉得我的这个方法应该可以满足所有树形结构的数据封装。在PC端,APP端已得到验证 思路 树形结构根据不同的条件需求找寻共通点,不管任何的业务需求,树形列表总要满足一下几个方面(不保证完全覆盖,欢迎大家完善): 1,树形节点的内容(title) 2, 树形节点id

camel_gold的博客 2093

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

java构建树形结构

在我们实际开发中会接触到树形结构,根节点子节点, 然后添加数据构成了我们的树形结构, 在Java后台利用递归思路进行构建数据,返回给前端,能以下拉菜单等形式进行展示, 以某市行政区为例。

m0_61682705的博客 1万+

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Java树形结构设计与开发

树形结构是我们开发过程中经常遇到的一种数据结构 例如:权限树,菜单树,分类树……

zukxu123的博客 6158

java中的树形结构构建器

在java程序员的平时工作中除了会遇到普通的集合类型,也免不了会遇到树形结构。这种数据结构相比简单的List、Set、Map相对来说会更加复杂一些,jdk中也没有对应的数据类型可以表示。所以开发者们在面对这一类的数据结构的时候总是需要自己来构建。例如下面这个例子。 例1:权限与菜单。我们可以构想这样一个场景。在一个OA系统中,不同权限/角色的用户登录需要在前端html中展现不同...

yuhelve3308的博客 597

一棵树的成长史——JAVA如何把数据库的数据处理成树形结构(核心代码直接使用即可)

JAVA如何把数据库的数据处理成树形结构?

菜菜bu菜的博客 1万+

java 通用树_Java 基于反射的通用树形结构工具类

在日常的开发中, 经常会遇到许多树形结构的场景, 如菜单树, 部门树, 目录树等. 而这些一般都会涉及到要将数据库查询出来的集合转化为树形结构的功能. 由于 list -> tree 是一个比较通用的功能, 无非就是根据 id, pid, children 这三个字段进行转换. 但由于字段名可能不一致, 如菜单里可能叫 menuId, 而部门里叫 deptId,所以我用反射来实现了一个通用的...

weixin_30284125的博客 411

java 数据库树形结构查询

1.什么是树形结构 见明知意,和大树差不多的结构,首先是有根,根下面有树枝,树枝下面又有叶子,一层包着一层 在项目中,一般菜单栏会用到这种结构 ...

jj2320711457的博客 4262

java递归构建树形结构

只有一个根节点数据结构: 1、准备表结构及对应的表数据 a、表结构: create table TB_TREE ( CID NUMBER not null, CNAME VARCHAR2(50), PID NUMBER //父节点 ) b、表数据: insert into tb_tree (CID, CNAME, PID) values (1, '中国', 0); insert i...

qq_42765276的博客 2万+
上一篇: Properties Editor for Eclipse
下一篇: 如何编写子定义annotation及使用JDK5.0 annotation包中的annotations
subchen
博客等级 码龄25年 33粉丝 77原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值