数据库表自连接 Java 应用程序表示形式



我有一个具有以下结构的数据库表:

CREATE TABLE `Professions` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `profession` varchar(254) NOT NULL,
  `profession_type` enum('system','custom') NOT NULL,
  PRIMARY KEY (`id`),
  KEY `profession_index` (`profession`)
) ENGINE=InnoDB AUTO_INCREMENT=296 DEFAULT CHARSET=utf8
 CREATE TABLE `Professions_Professions` (
  `parent_id` bigint(20) unsigned NOT NULL,
  `child_id` bigint(20) unsigned NOT NULL,
  PRIMARY KEY (`parent_id`,`child_id`),
  UNIQUE KEY `child_id_UNIQUE` (`child_id`),
  KEY `parent_id_index` (`parent_id`),
  CONSTRAINT `fk_Professions_Professions1` FOREIGN KEY (`parent_id`) REFERENCES `Professions` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_Professions_Professions2` FOREIGN KEY (`child_id`) REFERENCES `Professions` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8

为了获得职业的整个结构,我编写了以下SQL:

SELECT id, profession, profession_type, parent_id FROM Professions P LEFT OUTER JOIN Professions_Professions PP ON PP.child_id = P.id;

现在,我想在 Java 应用程序中表示这种类型的结构(我的位置表结构几乎相同)。
对我来说,创建某种没有根的树,而是一个充当根的元素列表看起来很合理。每个元素都将实现"Node"接口,该接口将允许获取其父元素和子元素列表。由于这应该是通用解决方案,因此我希望有一个通用树。
我还想有一个程序来上下走动这棵树并执行一些操作(接口)(在每个子项和每个子项列表上 - "节点"和"节点列表"操作),这些操作可以返回一些值或不返回,并且可以接受任意数量的参数。
如果操作将具有返回值,我希望其返回类型由操作实现指定。
我试图实现这一点,最终得到了以下代码(应该有很多笨拙......

// Removed the generic because i was unable to figure out how to make it all work ... 
public interface TreeNode {
    public void setParent(Object parent);
    public void setChildList(List childList);
    public Object getParent();
    public List getChildList();
}
public class Tree<T extends TreeNode> {
    private List<T> tree;
    public Tree(List<T> treeNodeList) {
        /* Ensuse that the list is not empty */
        if((null != treeNodeList) && (!treeNodeList.isEmpty())) {
            tree = new ArrayList<T>();
            /* Link the elements and create the tree */
            for(T node:treeNodeList) {
                /* If the current node has a parent */
                if(null != node.getParent()) {
                    /* Look the actual parent object in the initial node list */
                    int parentIndex = treeNodeList.indexOf(node.getParent());
                    if(-1 != parentIndex) {
                        T parent = treeNodeList.get(parentIndex);
                        /* Set the actual parent */
                        node.setParent(parent);
                        /* Add node to parent children list */
                        if(null == parent.getChildList()) {
                            parent.setChildList(new ArrayList<T>());
                        }
                        parent.getChildList().add(node);
                    }
                }
                else {
                    /* Add element to tree root list */
                    tree.add(node);
                }
            }
        }
    }

    public List<?> getRootList() {
        return tree;
    }
    public void forEachChild(List<T> rootList, SimpleNodeTreeAction<T> action, Object... args) {
        if((null != rootList) && (!rootList.isEmpty())) {
            Object[] localArgs = null;
            for(T node:rootList) {
                /* Store the local copy of args */
                if(null != args) {
                    localArgs = args.clone();
                }
                action.doAction(node, localArgs);
                forEachChild(node.getChildList(), action, localArgs);
            }
        }
    }
    public void forEachChild(T rootNode, SimpleNodeTreeAction<T> action, Object... args) {
        if(null != rootNode) {
            forEachChild(rootNode.getChildList(), action, args);
        }
    }
    public void forEachChild(SimpleNodeTreeAction<T> action, Object... args) {
        forEachChild(tree, action, args);
    }
    public Object forEachChild(List<T> rootList, NodeTreeAction<T> action, Object... args) {
        Object result = null;
        if((null != rootList) && (!rootList.isEmpty())) {
            Object[] localArgs = null;
            for(T node:rootList) {
                /* Store the local copy of args */
                if(null != args) {
                    localArgs = args.clone();
                }
                result = action.doAction(node, localArgs);
                if(null == result) {
                    result = forEachChild(node.getChildList(), action, localArgs);
                    if(null != result) {
                        break;
                    }
                }
                else {
                    break;
                }
            }
        }
        return result;
    }
    public Object forEachChild(T rootNode, NodeTreeAction<T> action, Object... args) {
        Object result = null;
        if(null != rootNode) {
            result = forEachChild(rootNode.getChildList(), action, args);
        }
        return result;
    }
    public Object forEachChild(NodeTreeAction<T> action, Object... args) {
        return forEachChild(tree, action, args);
    }
    public void forEachChildList(List<T> rootList, SimpleNodeListTreeAction<T> action, Object... args) {
        if((null != rootList) && (!rootList.isEmpty())) {
            action.doAction(rootList, args);
            for(T node:rootList) {
                forEachChildList(node.getChildList(), action, args);
            }
        }
    }
    public void forEachChildList(T rootNode, SimpleNodeListTreeAction<T> action, Object... args) {
        if(null != rootNode) {
            forEachChildList(rootNode.getChildList(), action, args);
        }
    }
    public void forEachChildList(SimpleNodeListTreeAction<T> action, Object... args) {
        forEachChildList(tree, action, args);
    }
    public Object forEachChildList(List<T> rootList, NodeListTreeAction<T> action, Object... args) {
        Object result = null;
        if((null != rootList) && (!rootList.isEmpty())) {
            result = action.doAction(rootList, args);
            if(null == result) {
                for(T node:rootList) {
                    result = action.doAction(node.getChildList(), args);
                    if(null != result) {
                        break;
                    }
                }
            }
        }
        return result;
    }
    public Object forEachChildList(T rootNode, NodeListTreeAction<T> action, Object... args) {
        Object result = null;
        if(null != rootNode) {
            result = forEachChildList(rootNode.getChildList(), action, args);
        }
        return result;
    }
    public Object forEachChildList(NodeListTreeAction<T> action, Object... args) {
        return forEachChildList(tree, action, args);
    }
    public void forEachParent(T rootNode, SimpleNodeTreeAction<T> action, Object... args) {
        if(null != rootNode) {
            T parent = (T) rootNode.getParent();
            while(null != parent) {
                action.doAction(parent, args);
                parent = (T) parent.getParent();
            }
        }
    } 
    public Object forEachParent(T rootNode, NodeTreeAction<T> action, Object... args) {
        Object result = null;
        if(null != rootNode) {
            T parent = (T) rootNode.getParent();
            while(null != parent) {
                result = action.doAction(parent, args);
                if(null == result) {
                    parent = (T) parent.getParent();
                }
                else {
                    break;
                }
            }
        }
        return result;
    }
    public Object search(final T searchObject) {
        return forEachChild(
                new NodeTreeAction<T>() {
                    @Override
                    public Object doAction(T node, Object... args) {
                        if(node.equals(searchObject)) {
                            return node;
                        }
                        else {
                            return null;
                        }
                    }
                },
                searchObject);
    } 
    public void sort(final Comparator comparator) {
        forEachChildList(
                new SimpleNodeListTreeAction<T>() {
                    @Override
                    public void doAction(List node, Object... args) {
                        Collections.sort(node, comparator);
                    }
                }, (Object) null);
    }
    public void sort() {
        forEachChildList(
                new SimpleNodeListTreeAction<T>() {
                    @Override
                    public void doAction(List node, Object... args) {
                        Collections.sort(node);
                    }
                }, (Object) null);
    }
}
public interface NodeTreeAction<T extends TreeNode> {
    public Object doAction(T node, Object... args);
}
public interface SimpleNodeTreeAction<T extends TreeNode> {
    public void doAction(T node, Object... args);
}
public interface NodeListTreeAction<T extends TreeNode> {
    public Object doAction(List<T> node, Object... args);
}
public interface SimpleNodeListTreeAction<T extends TreeNode> {
    public void doAction(List<T> node, Object... args);
}

谁能指出我如何使这个(假设不完美)解决方案变得更好(例如,从方法中返回实际的类型对象,而不是现在的对象)。如果有人能提出更好的解决方案,我将不胜感激。

提前感谢...

Meh.使 Node 成为 Tree 的内部类。这使得泛型声明更简单。如果要懒惰地创建向上和向下集合,请添加一些空检查。

尚未测试/编译此内容。扬子晚报.

class Tree<T implements Comparable<? super T>> {
  final Collection<Node> sourceNodes = new HashSet<Node>();
  final Collection<Node> sinkNodes = new HashSet<Node>();
  final Map<T, Node<T>> allNodes = new HashMap<T, Node<T>>();
  class Node implements Comparable<Node> {
      final T t;
      final Collection<Node> up = new HashSet<Node>();
      final Collection<Node> down = new HashSet<Node>();
      Node(t) {if(t==null) throw new IllegalArgumentException(); this.t = t;}
      public int hashCode() { return t.hashCode; }
      public int equals(Node n) { return t.equals(n.t);}
      public int compareTo(Node n) { return t.compareTo(n.t);}
  }
  void makeNewNode(T t) {
    Node n = new Node(t);
    sourceNodes.add(n);
    sinkNodes(n);
    alNodes.add(t,n);
  }
  void link(T up, T down) {
    link(all.get(up), all.get(down));
  }
  void link(Node up, Node down) {
    sourceNodes.remove(down); // no need to check
    sinkNodes.remove(up); // no need to check
    up.down.add(down);
    down.up.add(up);
  }
  void unlink(T up, T down) {
    unlink(all.get(up), all.get(down));
  }
  void unlink(Node up, Node down) {
      up.down.remove(down);
      down.up.remove(up);
      if(up.down.isEmpty()) sinkNodes.add(up);
      if(down.up.isEmpty()) sourceNodes.add(down);
  }
}

相关内容

最新更新