日期:2014-05-16  浏览次数:20448 次

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

我们通常会在应用中碰到树形结构的内容,比如 文件夹/文件模型, 部门组织结构,目录树等等,通常在设计模式中叫做 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 {
                    T