无限级部门

前言:前些天面试,发现面试官很喜欢问树的构造问题,我当时回答树设计就是通过一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国外业务部
|-1003财务部;

    * 其实我们还可以列简化,如果一棵非常大,我们不用把所有的节点都查出来,那样太浪费时间,我们可以要据需要来查用户的节点。
    * 比如说我们一CSDN网站左边的树,我们进到CSDN网站以后其实并不是每个节点都是我们想要进的,比如我可能只看java方面的,
    * 像.net,C,C#方面的,我可能就不会打开,这样就没必要把这些树给构造出来。我们只构造我们想要的树,其实也是动态构造的树。
    * 第一次时我们只构造一级节点,在sql条件中加lev=1;就可以了。用户进来后点击相应的节点再把这个节点的子节点查上来。这样

    * 就根据用户的须要给他生成相应的树,查他的子节点也很简单,只要查code 包含父节点编码就可以了。如:code like '1002%'* 这样就把业务部下面的都查出来了。

在这里将这将表里面的数据转为树对像,我是用递归来实现的,总感觉不是很好,不知还有没有更好的方法,求解答


public class depart {
    
    private int id;
    
    private String code;
    
    private int lev;
    
    private String name;
    
    private List<depart> list;


    public List<depart> getList() {
        return list;
    }

    public void setList(List<depart> list) {
        this.list = list;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public int getLev() {
        return lev;
    }

    public void setLev(int lev) {
        this.lev = lev;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

public class ConnectionUtil {
    private static Connection connection=null;
    static {
        try{
            Class.forName("com.mysql.jdbc.Driver");
            String url="jdbc:mysql://localhost/test?useUnicode=true&amp;characterEncoding=UTF8";
            String name="root";
            String password="root";
            connection=DriverManager.getConnection(url,name,password);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static Connection getConnection() {
        return connection;
    }
    public static void closeConnection(Connection connction){
        if(connction!=null){
            try {
                connction.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}


public class Test {
    /**
     * @param args
     */
    public static void main(String[] args) {
        Test test=new Test();
        try {
            test.testconnection();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    public void testconnection() throws Exception{
        String sql = "select t.* from depart t order by t.code ";
        Connection con=ConnectionUtil.getConnection();
        PreparedStatement st = con.prepareStatement(
                sql);
        ResultSet rs = st.executeQuery();
        List<depart> list=new LinkedList<depart>();
        while (rs.next()) {
            int lev=rs.getInt("lev");
            String code=rs.getString("code");
            String name=rs.getString("name");
             depart d=new depart();
             d.setCode(code);
             d.setLev(lev);
             d.setName(name);
             list.add(d);
        }
        ConnectionUtil.closeConnection(con);
        depart tt=new depart();
        for(int i=0;i<list.size();i++)
        {
            depart d=list.get(i);
            if(d.getLev()==1){
                if(tt.getList()!=null){
                    tt.getList().add(d);
                }
                else{
                    List<depart> ww=new ArrayList<depart>();
                    ww.add(d);
                    tt.setList(ww);
                }
            }else{
                ss(tt,d);
            }
        }
        
        System.out.println(JSON.toJSONString(tt));
    }
    
    
    public void ss(depart d,depart tt){
        if(d.getList()!=null){
            for(int s=0;s<d.getList().size();s++){
                depart u=d.getList().get(s);
                String code=tt.getCode().substring(0,tt.getCode().length()-2);
                int lev=tt.getLev();
                if(u.getCode().equals(code) && lev==u.getLev()+1){
                    if(d.getList().get(s).getList()!=null){
                        d.getList().get(s).getList().add(tt);
                    }
                    else{
                        List<depart> ii=new ArrayList<depart>();
                        ii.add(tt);
                        d.getList().get(s).setList(ii);
                    }
                    return;
                }
                ss(u,tt);
                
            }
        }
        
    }

}



















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值