最近在弄一个无限级的分类,上网搜了很多资料,感觉都不是很适用,仔细研究了下递归,并参考了老师的程序,终于弄出了点眉目,写出来和大家分享下,直接从项目里面拷出代码,稍做了点修改。
第一次在javaeye上写原创,不足之处请大家谅解。
数据库表的设计
数据库名为:business
表名为:news_class???? //新闻分类表
为简化说明,只写了3个字段,分别为:
1、newsclass_id?????? //分类ID,int 类型
2、newsclass_parentid //父ID,int 类型,这是分级关键,比如A的ID为B的父ID,说明A是B的父
????????????????????????????????????????????? 分类,以次类推,可以一级一级往下无限增长???????????????????????????
3、newsclass_title??? //分类的标题,varchar类型
插入20条记录
+--------------+--------------------+-----------------+
| newsclass_id | newsclass_parentid | newsclass_title |
+--------------+--------------------+-----------------+
|??????????? 1 |????????????????? 0 | title1????????? |
|??????????? 2 |????????????????? 1 | title2????????? |
|??????????? 3 |????????????????? 1 | title3????????? |
|??????????? 4 |????????????????? 1 | title4????????? |
|??????????? 5 |????????????????? 2 | title5????????? |
|??????????? 6 |????????????????? 2 | title6????????? |
|??????????? 7 |????????????????? 2 | title7????????? |
|??????????? 8 |????????????????? 0 | title8????????? |
|??????????? 9 |????????????????? 2 | title9????????? |
|?????????? 10 |????????????????? 2 | title10???????? |
|?????????? 11 |????????????????? 2 | title11???????? |
|?????????? 12 |????????????????? 0 | title12???????? |
|?????????? 13 |????????????????? 0 | title13???????? |
|?????????? 14 |????????????????? 0 | title14???????? |
|?????????? 15 |???????????????? 10 | title15???????? |
|?????????? 16 |????????????????? 1 | title16???????? |
|?????????? 17 |????????????????? 0 | title17???????? |
|?????????? 18 |???????????????? 15 | title18???????? |
|?????????? 19 |????????????????? 0 | pc1???????????? |
|?????????? 20 |???????????????? 18 | 111111????????? |
+--------------+--------------------+-----------------+
创建数据库连接
递归程序
输出结果为
总结
1、ID和父ID之间的关系
从数据库和输出结果可以观察出,父ID为0的分类为顶级分类,之上再无父级
如title 1、8、12、13、14、17、pc1这几个都是顶级分类
而如title 2、3、4、16,他们的父ID为1,也就是title1的ID,则他们就是title1的子分类
而同时也有一些记录的父ID指定到title 2、3、4、16的ID上,所以title 2、3、4、16之中也有自己的子类
如title 2、10,上面有父级分类,下面也有子级分类
2、parentid = rs.getInt(1) ;
在showTree方法中,因为我们parentid初始值设定是0,所以第一次的结果获取到的应该是先把title1输出
然后接着parentid = rs.getInt(1),这句话就是说把title1的ID放到parentid里,title1的ID为1,所以这时候的parentid的值改变为1,这样下面的
showTree(parentid,level+1,sql) ;就会从parentid为1开始查询,查询title1的子分类,再把子分类的ID放到parentid里,又查询子分类的子子分类,以次类推下去,直到把所有的子类都查询出来为止。
个人认为递归是关键,理解好递归了才好做出来
第一次在javaeye上写原创,不足之处请大家谅解。
数据库表的设计
数据库名为:business
表名为:news_class???? //新闻分类表
为简化说明,只写了3个字段,分别为:
1、newsclass_id?????? //分类ID,int 类型
2、newsclass_parentid //父ID,int 类型,这是分级关键,比如A的ID为B的父ID,说明A是B的父
????????????????????????????????????????????? 分类,以次类推,可以一级一级往下无限增长???????????????????????????
3、newsclass_title??? //分类的标题,varchar类型
插入20条记录
+--------------+--------------------+-----------------+
| newsclass_id | newsclass_parentid | newsclass_title |
+--------------+--------------------+-----------------+
|??????????? 1 |????????????????? 0 | title1????????? |
|??????????? 2 |????????????????? 1 | title2????????? |
|??????????? 3 |????????????????? 1 | title3????????? |
|??????????? 4 |????????????????? 1 | title4????????? |
|??????????? 5 |????????????????? 2 | title5????????? |
|??????????? 6 |????????????????? 2 | title6????????? |
|??????????? 7 |????????????????? 2 | title7????????? |
|??????????? 8 |????????????????? 0 | title8????????? |
|??????????? 9 |????????????????? 2 | title9????????? |
|?????????? 10 |????????????????? 2 | title10???????? |
|?????????? 11 |????????????????? 2 | title11???????? |
|?????????? 12 |????????????????? 0 | title12???????? |
|?????????? 13 |????????????????? 0 | title13???????? |
|?????????? 14 |????????????????? 0 | title14???????? |
|?????????? 15 |???????????????? 10 | title15???????? |
|?????????? 16 |????????????????? 1 | title16???????? |
|?????????? 17 |????????????????? 0 | title17???????? |
|?????????? 18 |???????????????? 15 | title18???????? |
|?????????? 19 |????????????????? 0 | pc1???????????? |
|?????????? 20 |???????????????? 18 | 111111????????? |
+--------------+--------------------+-----------------+
创建数据库连接
- package?com.common; ??
- import?java.sql.*?; ??
- public?class?DBConnection?{ ??
- ???? ??
- ????private?String?DB?=?"com.mysql.jdbc.Driver"?; ??
- ????private?String?URL?=?"jdbc:mysql://localhost/business"?; ??
- ????private?String?NAME?=?"root"?; ??
- ????private?String?PWD?=?"123456"?; ??
- ????private?Connection?conn?=?null?; ??
- ???? ??
- ???? ??
- ???? ??
- ????public?DBConnection(){ ??
- ????????try{ ??
- ????????????Class.forName(DB)?; ??
- ????????????conn?=?DriverManager.getConnection(URL,NAME,PWD)?; ??
- ????????}catch(Exception?e){ ??
- ????????????System.out.println(e); ??
- ???????????????? ??
- ????????} ??
- ???? ??
- ????} ??
- ???? ??
- ????public?Connection?getConnection(){ ??
- ????????return?this.conn?; ??
- ????} ??
- ???? ??
- ????public?void?close(ResultSet?rs?,?PreparedStatement?pstm){ ??
- ????????try{ ??
- ????????????conn.close()?; ??
- ????????????rs.close(); ??
- ????????????pstm.close()?; ??
- ???????????? ??
- ????????}catch(Exception?e){ ??
- ????????????System.out.println(e); ??
- ????????} ??
- ???????? ??
- ????} ??
- ??
- }??
package com.common; import java.sql.* ; public class DBConnection { private String DB = "com.mysql.jdbc.Driver" ; private String URL = "jdbc:mysql://localhost/business" ; private String NAME = "root" ; private String PWD = "123456" ; private Connection conn = null ; public DBConnection(){ try{ Class.forName(DB) ; conn = DriverManager.getConnection(URL,NAME,PWD) ; }catch(Exception e){ System.out.println(e); } } public Connection getConnection(){ return this.conn ; } public void close(ResultSet rs , PreparedStatement pstm){ try{ conn.close() ; rs.close(); pstm.close() ; }catch(Exception e){ System.out.println(e); } } }
递归程序
- package?com.test?; ??
- ??
- ????import?java.sql.PreparedStatement; ??
- import?java.sql.ResultSet; ??
- import?java.util.ArrayList; ??
- import?java.util.List; ??
- ??
- import?com.common.DBConnection; ??
- import?com.vo.NewsClass; ??
- ??
- ????public?class?Test?{ ??
- ???????? ??
- ????????List?l?=?new?ArrayList()?; ??
- ???????????DBConnection?dbc?=?new?DBConnection()?; ??
- ???????????PreparedStatement?pstm?=?null?; ??
- ??
- /* ?
- ?这里的int?parentid和String?sql说明 ?
- 1、parentid就是父ID,想从哪一层开始查询就输入相应的数字,一般父ID为0的是顶级分类,下面程序以父ID为0做演示 ?
- 2、因为我有几个表都要调用到递归,所以我没有把sql写死,设置为从外面传进来,这样不同表就可以有不同的sql语句了 ?
- ?*/??? ??
- ???????????public?ResultSet?child(int?parentid,String?sql){ ??
- ???????????????ResultSet?rs2?=?null?; ??
- ???????????????try{ ??
- ???????????????????pstm?=?dbc.getConnection().prepareStatement(sql)?; ??
- ???????????????????pstm.setInt(1,parentid)?; ??
- ????????????????????rs2?=?pstm.executeQuery()?; ??
- ???????????????}catch(Exception?e){? ??
- ???????????????}??????????????? ??
- ???????????????return?rs2?;???????????? ??
- ???????????} ??
- ??????????? ??
- //递归的方法? ??
- ???? ??
- ???????????public?void?showTree(int?parentid,int?level,String?sql)throws?Exception{?//level就是用于分出层次结构?????????????????? ??
- ??????????????ResultSet?rs?=?child(parentid,sql)?;//查询父ID,把该层查询到的数据都存放到resultset里面,因为我们查询的父ID是0,所以第一次运行时查询出的是最顶层 ??
- ???????????????try{ ??
- ???????????????????while(rs.next()){ ??
- ??????????????????????//?System.out.println(rs.getString(3))?; ??
- ???????????????????????parentid?=?rs.getInt(1)?;//此处是关键,把获取到的数据的ID存到parentid中,那么下面递归的时候就会查询出该记录是否有子分类了?????????????????????String?str?=?"|___?"?; ??
- ???????????????????????for(int?i=0;i<level;i++){//判断level,每加一级就多一个...,这样显示出层次感 ??
- ?????????????????????????????str="?.?.?.?"+str?; ??
- ???????????????????????} ??
- ??
- ???????????????????????System.out.println(str+rs.getString(3));//输出结果 ??
- ???????????????????????showTree(parentid,level+1,sql)?;?//递归开始了,再次调用自身方法 ??
- ???????????????????}???? ??
- ???????????????}catch(Exception?e){???????????????? ??
- ???????????????} ??
- ???????????} ??
- ???????????public?static?void?main(String?args[])throws?Exception{ ??
- ???????????????String?sql?=?"select?*?from?news_class?where?newsclass_parentid=?"?;//自己定义sql,这样比较灵活,根据父ID查询出数据 ??
- ???????????????Test?tree?=?new?Test()?; ??
- ???????????????tree.showTree(0,?0,?sql)?;//为了演示,从父ID为0,也就是顶级分类开始查询 ??
- ???????????}???? ??
- ????}??
package com.test ; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; import com.common.DBConnection; import com.vo.NewsClass; public class Test { List l = new ArrayList() ; DBConnection dbc = new DBConnection() ; PreparedStatement pstm = null ; /* 这里的int parentid和String sql说明 1、parentid就是父ID,想从哪一层开始查询就输入相应的数字,一般父ID为0的是顶级分类,下面程序以父ID为0做演示 2、因为我有几个表都要调用到递归,所以我没有把sql写死,设置为从外面传进来,这样不同表就可以有不同的sql语句了 */ public ResultSet child(int parentid,String sql){ ResultSet rs2 = null ; try{ pstm = dbc.getConnection().prepareStatement(sql) ; pstm.setInt(1,parentid) ; rs2 = pstm.executeQuery() ; }catch(Exception e){ } return rs2 ; } //递归的方法 public void showTree(int parentid,int level,String sql)throws Exception{ //level就是用于分出层次结构 ResultSet rs = child(parentid,sql) ;//查询父ID,把该层查询到的数据都存放到resultset里面,因为我们查询的父ID是0,所以第一次运行时查询出的是最顶层 try{ while(rs.next()){ // System.out.println(rs.getString(3)) ; parentid = rs.getInt(1) ;//此处是关键,把获取到的数据的ID存到parentid中,那么下面递归的时候就会查询出该记录是否有子分类了 String str = "|___ " ; for(int i=0;i<level;i++){//判断level,每加一级就多一个...,这样显示出层次感 str=" . . . "+str ; } System.out.println(str+rs.getString(3));//输出结果 showTree(parentid,level+1,sql) ; //递归开始了,再次调用自身方法 } }catch(Exception e){ } } public static void main(String args[])throws Exception{ String sql = "select * from news_class where newsclass_parentid=?" ;//自己定义sql,这样比较灵活,根据父ID查询出数据 Test tree = new Test() ; tree.showTree(0, 0, sql) ;//为了演示,从父ID为0,也就是顶级分类开始查询 } }
输出结果为
- |___?title1 ??
- ?.?.?.?|___?title2 ??
- ?.?.?.??.?.?.?|___?title5 ??
- ?.?.?.??.?.?.?|___?title6 ??
- ?.?.?.??.?.?.?|___?title7 ??
- ?.?.?.??.?.?.?|___?title9 ??
- ?.?.?.??.?.?.?|___?title10 ??
- ?.?.?.??.?.?.??.?.?.?|___?title15 ??
- ?.?.?.??.?.?.??.?.?.??.?.?.?|___?title18 ??
- ?.?.?.??.?.?.??.?.?.??.?.?.??.?.?.?|___?111111??
- ?.?.?.??.?.?.?|___?title11 ??
- ?.?.?.?|___?title3 ??
- ?.?.?.?|___?title4 ??
- ?.?.?.?|___?title16 ??
- |___?title8 ??
- |___?title12 ??
- |___?title13 ??
- |___?title14 ??
- |___?title17 ??
- |___?pc1??
|___ title1 . . . |___ title2 . . . . . . |___ title5 . . . . . . |___ title6 . . . . . . |___ title7 . . . . . . |___ title9 . . . . . . |___ title10 . . . . . . . . . |___ title15 . . . . . . . . . . . . |___ title18 . . . . . . . . . . . . . . . |___ 111111 . . . . . . |___ title11 . . . |___ title3 . . . |___ title4 . . . |___ title16 |___ title8 |___ title12 |___ title13 |___ title14 |___ title17 |___ pc1
总结
1、ID和父ID之间的关系
从数据库和输出结果可以观察出,父ID为0的分类为顶级分类,之上再无父级
如title 1、8、12、13、14、17、pc1这几个都是顶级分类
而如title 2、3、4、16,他们的父ID为1,也就是title1的ID,则他们就是title1的子分类
而同时也有一些记录的父ID指定到title 2、3、4、16的ID上,所以title 2、3、4、16之中也有自己的子类
如title 2、10,上面有父级分类,下面也有子级分类
2、parentid = rs.getInt(1) ;
在showTree方法中,因为我们parentid初始值设定是0,所以第一次的结果获取到的应该是先把title1输出
然后接着parentid = rs.getInt(1),这句话就是说把title1的ID放到parentid里,title1的ID为1,所以这时候的parentid的值改变为1,这样下面的
showTree(parentid,level+1,sql) ;就会从parentid为1开始查询,查询title1的子分类,再把子分类的ID放到parentid里,又查询子分类的子子分类,以次类推下去,直到把所有的子类都查询出来为止。
个人认为递归是关键,理解好递归了才好做出来