表中三个字段
id name childid
1 根目录1 0
2 根目录2 0
3 子目录1 1
4 子目录2 1
5 子目录3 2
6 子目录4 2
…………ID自动生成的,
childid就是 属于哪个的子分类,就是那个分类的ID编号,
从数据库读回来内容后,
怎么能对他实现自动分类呢,归属哪个类别就在哪个类别的下面.
也就是对分类实现能够无限分类,
查了下,都说用递归实现,
谁能给个例子看下吗,
从数据库查回来内容以后就不会弄了,郁闷.

解决方案 »

  1.   

    不是很明白楼主的意思不过如果用ORACLE数据库的话,可以用下面的查询语句进行查询:SELECT LEVEL, b.* FROM TABLE_NAME b CONNECT BY PRIOR b.id=b.childid START WITH b.childid=0(有两个建议:第一,childid改名为parentid,因为你这个明显是父节点编号;第二,把childid作一个可以为空的FK,否则你将来会不好处理)查询得结果:
    level id name     childid
    1     1  根目录1   0
    2     3  子目录1   1
    2     4  子目录2   1
    1     2  根目录2   0
    2     5  子目录3   2
    2     6  子目录4   2这样查询出来的就是树形结构了。如果需要在页面显示,可以用dtree.js控件显示成树形菜单可以用我写的ctreetable.js控件显示成树形表格
    或者用ctreeselector.js控件显示成树形下拉框
    (下载地址:http://download.csdn.net/source/171981)以上控件都不支持数据库动态加载,ctreetable和ctreeselector支持页面动态加载。如果需要数据库动态加载,可以找找AJAX的树形控件。
      

  2.   

    可能开始想要描述的不怎么清楚,还有就是childid这个也写错了,应该是他的父级分类,parentid,不是childid的,呵呵。
    我自己这样写了一个,但是感觉这样的话,效率要低的多,因为好像要一直查库,每次都要循环一次,如果分类比较多的话,估计就用不了了。============================================================================
    package com.hmilyld.channel;import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;import com.hmilyld.study.DatabaseBean;public class ChannelBean {
    Connection conn ;
    public ChannelBean(){
    try {
    this.conn=DatabaseBean.getConnection();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    /*
     * 查库,得到库中所有分类
     */
    public Collection getChannel() throws SQLException{
    Collection<Channel> rs = new ArrayList<Channel>();
    Statement stm = conn.createStatement();
    ResultSet rst = stm.executeQuery("select * from channel");
    while (rst.next()){
    Channel channel = new Channel();
    channel.setChannelId(rst.getInt("id"));
    channel.setChannelName(rst.getString("name"));
    channel.setChannelParentId(rst.getInt("parentid"));
    rs.add(channel);
    }
    conn.close();
    return rs;
    }

    public static void main(String[] args) throws Exception{
    ChannelBean channel = new ChannelBean();
    Iterator it = channel.getChannel().iterator();
    while(it.hasNext()){
    Channel chan = (Channel)it.next();
    if(chan.getChannelParentId()==0){
    int i = chan.getChannelId();
    System.out.println(chan.getChannelName()); //打印出最顶级分类
    /*
     * 打印出顶级分类下的分类,然后调用channelSort
     */
    channel.channelSort(it,i);
    }
    }
    }

    public void channelSort(Iterator it,int id) throws Exception{
    ChannelBean channel = new ChannelBean();
    it = channel.getChannel().iterator();
    while (it.hasNext()){
    Channel chan = (Channel)it.next();
    int channelChildId = chan.getChannelParentId();
    int channelId = chan.getChannelId();
    if(channelChildId==id){
    System.out.println("--"+chan.getChannelName());
    /*
     * 一直循环调用
     */
    channelSort(it,channelId);
    }
    }
    }
    }
    ============================================================================这样似乎能一直无限分类下去,但是效率好像低的厉害,而且还有一个问题,
    就是如果我想按照这种方式显示的话,好像不行。根目录1
    --子目录1
    ----子目录11
    --子目录2因为在后面的循环调用的时候,就都按照System.out.println("--"+chan.getChannelName());
    这一句打印出来了,这应该怎么办?希望高人指点一下,5.1什么都没弄,就整这个东西了,郁闷.- -#
      

  3.   

    首先你在main方法中调用了getChannel()方法,已经把所有的分类的取到了。这个时候你应该把List保存起来,而不是每次都到数据库中取。public class ChannelBean {    private Collection<Channel> channelList = null;    public Collection getChannel() throws SQLException {
            if(this.channelList==null) {
                channelList = new ArrayList<Channel>();
                //原来的哪些,不要return
                //建议你用我前面回复的那个SQL语句,取得的结果集已经排序过了
                ...
                conn.close();
            }
            return channelList;
        }    public static void main(String[] args) {
            ChannelBean bean = new ChannelBean();
            channelBean.printChannel(0, 0);
        }    // 打印
        // 不按我的SQL语句排序的情况
        public void printChannel(int level, int parentId) {
            for(Iterator iter=this.getChannel().iterator(); iter.hasNext();) {
                Channel channel = (Channel) iter.next();
                if(channel.getParentId()==parentId) {
                    for(int i=0; i<level; i++) {
                        System.out.print("-");
                    }
                    System.out.println(channel.getName());
                    // 递归调用
                    printChannel(level + 1, channel.getChannelId());
                }
            }
        }
    }
      

  4.   

    这种方式的时间复杂度是n*n,所以确实效率很低。如果你用了CONNECT BY那句,时间复杂度可以降低,但是要使用堆栈,只要改写printChannel:    public void printChannel(int level, int parentId) {
            Stack stack = new Stack();// 我忘记堆栈的实现类是哪个了
            int pid = parentId;
            for(Iterator iter=this.getChannel().iterator(); iter.hasNext();) {
                Channel channel = (Channel) iter.next();
                if(channel.getParentId()==pid) {
                    for(int i=0; i<level; i++) {
                        System.out.print("-");
                    }
                    System.out.println(channel.getName());
                } else {
                    while(pid != channel.getParentId() && !stack.isEmpty())
                        // 当前pid已没有子节点,从stack出栈
                        pid = ((Integer) stack.pop()).intValue();
                        level--;
                    }
                }
                // 打印
                for(int i=0; i<level; i++) {
                    System.out.print("-");
                }
                System.out.println(channel.getName());
                // 把pid入栈,用当前id替换
                stack.push(new Integer(pid));
                pid = channel.getChannelId();
                level++;
           }
        }
      

  5.   

    ……不好意思,上面错了……我汗啊汗
        public void printChannel(int level, int parentId) {
            Stack stack = new Stack();// 我忘记堆栈的实现类是哪个了
            int pid = parentId;
            for(Iterator iter=this.getChannel().iterator(); iter.hasNext();) {
                Channel channel = (Channel) iter.next();
                while(pid != channel.getParentId() && !stack.isEmpty())
                    // 当前pid已没有子节点,从stack出栈
                    pid = ((Integer) stack.pop()).intValue();
                    level--;
                }
                // 打印
                for(int i=0; i<level; i++) {
                    System.out.print("-");
                }
                System.out.println(channel.getName());
                // 把pid入栈,用当前id替换
                stack.push(new Integer(pid));
                pid = channel.getChannelId();
                level++;
           }
        }
      

  6.   

    /**
    * 功能:对栏目进行无限级分类
    * 数据库表说明:
    *   id:自动编号
    *   name:栏目名称
    *   parentid:所属父级栏目编号,与id相对应
    * @author Hmilyld
    * @home  http://www.hmilyld.cn
    */
    package com.hmilyld.channel;import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;import com.hmilyld.study.DatabaseBean;public class ChannelBean {
     Connection conn; static Collection<Channel> rs = new ArrayList<Channel>();  //静态Collection,只存在一份rs,不需要每次都对数据库进行查询,提高效率
     
     /*
      * 得到Connection连接
      */
     public ChannelBean() {
       try {
         this.conn = DatabaseBean.getConnection();
       } catch (Exception e) {
         e.printStackTrace();
       }
     } /*
      * 查库,得到库中所有分类,返回Collection
      */
     public Collection getChannel() throws SQLException {
       Statement stm = conn.createStatement();
       ResultSet rst = stm.executeQuery("select * from channel");
       while (rst.next()) {
         Channel channel = new Channel();
         channel.setChannelId(rst.getInt("id"));
         channel.setChannelName(rst.getString("name"));
         channel.setChannelParentId(rst.getInt("parentid"));
         rs.add(channel);
       }
       conn.close();
       return rs;
     } public static void main(String[] args) throws Exception {
       ChannelBean channel = new ChannelBean();
       channel.getChannel();
       Iterator it = ChannelBean.rs.iterator();
       while (it.hasNext()) {
         Channel chan = (Channel) it.next();
         if (chan.getChannelParentId() == 0) {
           int i = chan.getChannelId();
           System.out.println(chan.getChannelName()); // 打印出最顶级分类
           /*
            * 打印出顶级分类下的分类,然后调用channelSort,传递栏目名称
            */
           ChannelBean.channelSort(it, i ,chan.getChannelName());
         }
       }
     }
     /*
      * 循环得到分类方法
      */
     public static void channelSort(Iterator it, int id ,String name) throws Exception {
       it = ChannelBean.rs.iterator();
       while (it.hasNext()) {
         Channel chan = (Channel) it.next();
         int channelChildId = chan.getChannelParentId();
         int channelId = chan.getChannelId();
         if (channelChildId == id) {
           System.out.println(name+"--" + chan.getChannelName());
           String na = name+"--"+chan.getChannelName();
           /*
            * 循环调用获取分类名称
            */
           channelSort(it, channelId ,na);
         }
       }
     }
    }
    又换了下,不过你说那个用堆栈的方式,不是太明白.呵呵.:)
    先结贴吧,暂时搞定勒,虽然效率低了点