1、这回先创建数据库吧
下表cid是CategoryId的缩写,cname是CategoryName的缩写,pid是parentId的缩写
无限级分类一般都包含这三个属性,至少也要包含cid和pid才能建立无限级关联
ok,这个东东就是无限级分类了。
即便是外行人稍微看一眼也能发现cid为1的图书在小说和周刊两行中作为了pid,也就是说小说和周刊的父级分类就是图书
图书和饮料的pid是0,代表他们是顶级分类
如果没有其他约束条件,这张表几乎可以无限向下级延伸,是一个树形结构,这里就不写什么数学公式了,道理很简单。想必大家都懂了。
2、写个实体类
首先还是生产实体类,植入一个他本身的List集合:
1 package cn.sohappy.acourses.bean;2
3 import java.util.ArrayList;4 import java.util.List;5
6 public classCategory {7 privateLong cid;8 privateString cname;9 privateLong pid;10 private List children;11
12 //省略getter and setter
13 }
然后初始化children并重写toString方法方便测试,完整代码如下:
1 package cn.sohappy.acourses.bean;2
3 import java.util.ArrayList;4 import java.util.List;5
6 public classCategory {7 privateLong cid;8 privateString cname;9 privateLong pid;10 private List children=new ArrayList();//这里为了防止后面空指针,初始化了children实例11
12 public ListgetChildren() {13 returnchildren;14 }15
16 public void setChildren(Listchildren) {17 this.children =children;18 }19
20 publicLong getCid() {21 returncid;22 }23
24 public voidsetCid(Long cid) {25 this.cid =cid;26 }27
28 publicString getCname() {29 returncname;30 }31
32 public voidsetCname(String cname) {33 this.cname =cname;34 }35
36 publicLong getPid() {37 returnpid;38 }39
40 public voidsetPid(Long pid) {41 this.pid =pid;42 }43
44 @Override45 publicString toString() {46 return "Category{cid:"+cid+
47 ",cname:"+cname+
48 ",pid:"+pid+
49 ",children:"+children+
50 "}";51 }52 }
3、写接口:
ListfindCategoriesByParentId(Long pid);自关联查询
ListfindAllCategories();一条sql查询所有,后期用Map算法分级
1 package cn.sohappy.acourses.course0921;2
3 import cn.sohappy.acourses.bean.Category;4
5 import java.util.List;6
7 public interfaceICategoryDAO {8 ListfindCategoriesByParentId(Long pid);9 ListfindAllCategories();10 }
4、小配置:
1 <?xml version="1.0" encoding="UTF-8" ?>
2 /p>
4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5
6
7
8
9
10
11
12
13
14 select * from category where pid=#{0}15
16
17
18
19
20
21
22
23 select * fromcategory24
25
5.测试类:
1 package cn.test;2
3 import cn.sohappy.acourses.bean.BillManyToOne;4 import cn.sohappy.acourses.bean.Category;5 import cn.sohappy.acourses.bean.UserOneToMany;6 import cn.sohappy.acourses.course0921.ICategoryDAO;7 import cn.sohappy.acourses.course0921.IUserDAO;8 import cn.sohappy.acourses.course0921.InfiniteMenuUtil;9 import cn.sohappy.bean.Smbms_user;10 import cn.sohappy.util.MyBatisUtil;11 import org.apache.ibatis.session.SqlSession;12 import org.junit.Test;13
14 import java.util.List;15
16 public classtest20170921 {17 @Test18 //自关联实现无穷分类
19 public voidselfCorrelation(){20 SqlSession session =MyBatisUtil.getSession();21 ICategoryDAO mapper = session.getMapper(ICategoryDAO.class);22 List categories = mapper.findCategoriesByParentId(0L);23 for(Category item :categories) {24 System.out.println(item);25 }26 session.close();27 }28 @Test29 //Map集合实现无穷分类
30 public voidInfiniteMenu(){31 SqlSession session =MyBatisUtil.getSession();32 ICategoryDAO mapper = session.getMapper(ICategoryDAO.class);33 List categoriesClassified = newInfiniteMenuUtil().loadMenu(mapper.findAllCategories());34 for(Category item :categoriesClassified) {35 System.out.println(item);36 }37 session.close();38 }39 }
6、InfiniteMenu的Map算法
1 package cn.sohappy.acourses.course0921;2
3 import java.lang.reflect.InvocationTargetException;4 import java.lang.reflect.Method;5 import java.util.*;6
7 public classInfiniteMenuUtil {8 @SuppressWarnings("unchecked")9 public List loadMenu(Listmenus) {10 List rootMenus = new ArrayList();11 if (menus != null && menus.size() != 0) {12 List methodsList = Arrays.asList(menus.get(0).getClass().getDeclaredMethods());13 //这里可以自己定制啦,我定制的是以pid,id,children结尾的get方法为分别getPid,getId,getChildren.所以menu类(Category)的属性名要符合定制规范
14 Method getId = null;15 Method getPid = null;16 Method getChildren = null;17 //get getMethod
18 for(Method item : methodsList) {19 if ("get".equals(item.getName().toLowerCase().substring(0,3))&&item.getName().length()>=6&&"pid".equals(item.getName().toLowerCase().substring(item.getName().length() - 3, item.getName().length()))){20 getPid =item;21 continue;22 }23 if ("get".equals(item.getName().toLowerCase().substring(0,3))&&item.getName().length()>=5&&"id".equals(item.getName().toLowerCase().substring(item.getName().length() - 2, item.getName().length()))){24 getId =item;25 continue;26 }27 if ("get".equals(item.getName().toLowerCase().substring(0,3))&&item.getName().length()>=11&&"children".equals(item.getName().toLowerCase().substring(item.getName().length() - 8, item.getName().length()))){28 getChildren =item;29 }30 }31 if (getId!=null&&getPid!=null&&getChildren!=null){32 //get menuMap
33 Map menuMap = new HashMap();34 for(T menu : menus) {35 Long id = null;36 try{37 id =(Long)getId.invoke(menu);38 } catch(IllegalAccessException e) {39 e.printStackTrace();40 } catch(InvocationTargetException e) {41 e.printStackTrace();42 }43 menuMap.put(id,menu);44 }45 //add children
46 for(T menu:menus) {47 Long pid = null;48 try{49 pid =(Long)getPid.invoke(menu);50 } catch(IllegalAccessException e) {51 e.printStackTrace();52 } catch(InvocationTargetException e) {53 e.printStackTrace();54 }55 if (pid==null||pid==0){56 rootMenus.add(menu);57 }else{58 T t = menuMap.get(pid);59 Listts;60 try{61 ts = (List) getChildren.invoke(t);62 ts.add(menu);63 } catch(IllegalAccessException e) {64 e.printStackTrace();65 } catch(InvocationTargetException e) {66 e.printStackTrace();67 }68 }69 }70 }71 }72 returnrootMenus;73 }74 }