目录树结构的数据库设计思考
转载地址:http://blog.csdn.net/sinat_22657459/article/details/52953362
昨天一同事遇到一问题,找我帮忙解决一下,他的需求是这样的,服务器将收集好的数据返回回来,客户端要解析并展现成树状的,类似于QQ客户端那样,大概就如下面这张图,这是他们网页端实现的界面。
其实需求挺简单,目录树最多分为三级,每个节点只有一个父目录,每个子点会有0个或者多个子目录。我们老是搞客户端,用到数据库的比较少,即使用到,也是很浅的。他们服务器的同事对目前的组织数据返回来的结果是下面这样的:
看到这样的数据,真是头疼了,估计他们开发服务器的哥们也是个新手,数据没有一点组织,这样的数据让他自己来解释,他能解释清楚吗?我当时想到的最直接的方案,就是数据库的设计应该分别对应三张表,分别是一级目录、二级目录、三级目录,三张表的设计大致相同,一级目录不需要parentId,只需要有一个id就行,二级目录和三级目录都需要有一个id和parentId的字段,标识自己和父目录,客户端请求的时候,那么就去查数据库,比如,按照上面第一张图的样子,我们以其中规费问题这个节点来说明,因为它有三级目录,理解更形象。先去查一级目录表,查到有规费问题这个节点,好,那么接下来就要确定他的二级目录了,再去查相应的二级目录表;碰到第一个节点,堤围防护费,好,有一个二级目录了,取出它的id作为三级目录的parentId,再用这个parentId去匹配三级目录中的id,三级目录查完,没有,好,那么一个完全的二级目录就生成了,此时,将它添加到一级目录,规费问题中。此时还在二级目录中,继续往下,又查到一个二级目录社会保险费,好,再以它的id作为parentId去查三级目录,好,查到有综合类问题、养老保险、医疗保险、失业保险、工伤保险、生育保险、其他这几个子目录,分别将每个子目录生成对应的三级目录存放在二级目录社会保险费下边,此时,又一个二级目录树组织好了,再将它添加到一级目录规费问题中,如此往复,直到所有的二级目录生成完毕,整个目录树也就组织好了,此时组织完成的数据大概是这样的:
{data:[{一级目录:[{二级目录:[{三级目录:"综合类问题", }, {三级目录:"养老保险", }, {三级目录:"", }]}, ]}, {一级目录:[]}, {一级目录:[]}, ……]}
客户端解析的实现大概如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
/**
* 组织整个目录树中的所有数据
*/
private void createTreeData() {
// 获取第一个节点的id,全部问题
String headId = mList.get(0).id;
superAdapter.RemoveAll();
superAdapter.notifyDataSetChanged();
List<SuperTreeViewAdapter.SuperTreeNode> superNodeTree = superAdapter
.GetTreeNode();
for (QuestionDirNode n1 : mList) {
// 匹配到一个一级目录
if (headId.equals(n1.parentId)) {
SuperTreeViewAdapter.SuperTreeNode superNode = new SuperTreeViewAdapter.SuperTreeNode();
superNode.parent = n1.name;
String firstDirId = n1.id;
for (QuestionDirNode n2 : mList) {
// 匹配到一个二级目录
if (firstDirId.equals(n2.parentId)) {
TreeViewAdapter.TreeNode node = new TreeViewAdapter.TreeNode();
node.parent = n2.name;
String secondDirId = n2.id;
for (QuestionDirNode n3 : mList) {
if (secondDirId.equals(n3.parentId)) {
// 匹配到一个三级目录
node.childs.add(n3.name);
}
}
superNode.childs.add(node);
}
}
superNodeTree.add(superNode);
}
}
superAdapter.UpdateTreeNode(superNodeTree);
listView.setAdapter(superAdapter);
}
|
来自CODE的代码片
这就是我当时回答同事的方案,后来晚上下班回家,坐在车上,想想这个问题,感觉有哪里不对。像这样的数据确实能很好的反应出当前的目录树的结构,但是服务器在查数据库和组织数据的时候,会不会很浪费时间?客户端拿到这样的数据,好不好解析呢?大家可以看到,因为有三级目录,所以对应的也有三层JsonArray,客户端解析的时候,应该需要三层for循环,不断去取出里边的元素,然后才能组织出一个完整的目录树,三层for循环,这是不是有点难以接受,这样的方案应该是有问题的吧,看来我们需要其他方案对他进行优化。
当然,我是个客户端的开发,设计出这样的数据库只能完成功能,在这方面,肯定还是服务器的同事经验丰富,于是随便百度一下,果然,有非常多的经验。
在这里呢,不打算说关于数据库设计类的东西,因为我也不精,还不如大家,只是有一点思考,我们以后在碰到这样的需求时,应该要先考虑好自己的方案设计,搞清楚实现思路,然后才能写代码,尤其像数据库这种东西,如果起初不考虑好,直接写代码,那后边遇到这样的问题,修改数据库表的设计就会非常复杂。
其次,我们在实现需求的过程中,应该要经常考虑每个实现步骤的效率和算法,这样才能提升我们的代码的质量。
总之一句话:磨刀不误砍柴功!!!