前言:前些天面试,发现面试官很喜欢问树的构造问题,我当时回答树设计就是通过一pid来保存父结点的id值来实现,通过递归
* 来生成一棵树,但是面试官说如果树比较大的话这样做的效率太低,网上找好像也都是这种方法,后来发现以前看用友的表
* 结构设计里没有用这种方法,他们采用的是下面的表结构设计。
1、树结构表的设计(bd_depart)部门
* id(主键),code(编码),name(名称),lev(级次),isleaf(是否叶子)
* 说明一下(lev)级次,这里没有父节点的id,只有一个级次,我们如果构造一棵部门树,
* 假如:有开发部,业务部,财务部,这些都是一级(级次),业务部下面分国内业务和国际业务
* 那国内业务和国外业务就是二级(级次),如果国内又分为华南,华北,华东,那这些就是三级。
* 当然光有级次还不行,他还是找不到父节点是哪个,我们这里有三个一级节点,那二级节点到底
* 放在哪个一级节点下呢,这里就是要看编码吗了;我们这里的编码是有规定的,假如我们规定级
* 次关系是4/2/2;我们假设是三级,他的意思是第一级是4位编码,第二级和第三级是2位编码。
* 如:开发部(1001),业务部(1002),财务部(1003);国内业务部(100201),国外业务部(100202)
* 这里的二级是6位了,因为他要加上他父级的4位,这样二级就可以找到他的父结点了。同样三级也
* 是在他的父级(二级)的基础上加二位编码。
2、为什么要这么设计
* 这种设计对于一棵大型树的效率是非常高的,我们一般都是用一个pid来保存他的父结点,
* 这种通过递归来实现一棵树,这种如果是一棵非常大的树的话是非常不好的。我们现在设计
* 的这种下面在查的时候是非常方便的。他只要访问一次数据库就可以了。
3、生成树
* String sql = "select t.* from bd_depart t order by t.code ";//查询数据库,非常简单的一个sql语句
* Connection con=ConnectionUtil.getConnection();//得到一个连接
* PreparedStatement st = con.prepareStatement(sql);
* ResultSet rs = st.executeQuery();
* while (rs.next()) {
* int lev=rs.getInt("lev");//得到级次
* for(int i=1;i<lev;i++){
* System.out.print(" ");
* }
* System.out.print("|-");
* System.out.println(rs.getString("code")+rs.getString("name"));
* }
* ConnectionUtil.closeConnection(con);//关闭连接
* 我们通过查询时根据编码排序便可以把这棵树查出来,他们rs中分别是
* 开发部,业务部,国内业务部,华南业务部,华北业务部,华东业务部,国外业务部,财务部;
* 通过判断级次来确定他的级次关系,我们这里是采用缩近的方式。打印如下:
|-1001开发部
|-1002业务部
|-100201国内业务部
|-10020101华南业务部
|-10020102华北业务部
|-10020103华东业务部
|-100202国外业务部
|-财务部;
* 其实我们还可以列简化,如果一棵非常大,我们不用把所有的节点都查出来,那样太浪费时间,我们可以要据需要来查用户的节点。
* 比如说我们一CSDN网站左边的树,我们进到CSDN网站以后其实并不是每个节点都是我们想要进的,比如我可能只看java方面的,
* 像.net,C,C#方面的,我可能就不会打开,这样就没必要把这些树给构造出来。我们只构造我们想要的树,其实也是动态构造的树。
* 第一次时我们只构造一级节点,在sql条件中加lev=1;就可以了。用户进来后点击相应的节点再把这个节点的子节点查上来。这样
* 就根据用户的须要给他生成相应的树,查他的子节点也很简单,只要查code 包含父节点编码就可以了。如:code like '1002%'
* 这样就把业务部下面的都查出来了。
- 1
- 2
- 3
前往页