一、這回先建立數據庫吧java
下表cid是CategoryId的縮寫,cname是CategoryName的縮寫,pid是parentId的縮寫算法
無限級分類通常都包含這三個屬性,至少也要包含cid和pid才能創建無限級關聯sql
ok,這個東東就是無限級分類了。數據庫
即使是外行人稍微看一眼也能發現cid爲1的圖書在小說和週刊兩行中做爲了pid,也就是說小說和週刊的父級分類就是圖書apache
圖書和飲料的pid是0,表明他們是頂級分類session
若是沒有其餘約束條件,這張表幾乎能夠無限向下級延伸,是一個樹形結構,這裏就不寫什麼數學公式了,道理很簡單。想必你們都懂了。mybatis
二、寫個實體類app
首先仍是生產實體類,植入一個他自己的List集合:ide
1 package cn.sohappy.acourses.bean; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 public class Category { 7 private Long cid; 8 private String cname; 9 private Long pid; 10 private List<Category> 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 class Category { 7 private Long cid; 8 private String cname; 9 private Long pid; 10 private List<Category> children=new ArrayList<Category>();//這裏爲了防止後面空指針,初始化了children實例 11 12 public List<Category> getChildren() { 13 return children; 14 } 15 16 public void setChildren(List<Category> children) { 17 this.children = children; 18 } 19 20 public Long getCid() { 21 return cid; 22 } 23 24 public void setCid(Long cid) { 25 this.cid = cid; 26 } 27 28 public String getCname() { 29 return cname; 30 } 31 32 public void setCname(String cname) { 33 this.cname = cname; 34 } 35 36 public Long getPid() { 37 return pid; 38 } 39 40 public void setPid(Long pid) { 41 this.pid = pid; 42 } 43 44 @Override 45 public String toString() { 46 return "Category{cid:"+cid+ 47 ",cname:"+cname+ 48 ",pid:"+pid+ 49 ",children:"+children+ 50 "}"; 51 } 52 }
三、寫接口:
List<Category> findCategoriesByParentId(Long pid);自關聯查詢
List<Category> findAllCategories();一條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 interface ICategoryDAO { 8 List<Category> findCategoriesByParentId(Long pid); 9 List<Category> findAllCategories(); 10 }
四、小配置:
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="cn.sohappy.acourses.course0921.ICategoryDAO"> 6 <!--01.自關聯查詢--> 7 <resultMap id="selectCategoriesByPid" type="cn.sohappy.acourses.bean.Category"> 8 <id property="cid" column="cid"/> 9 <result property="cname" column="cname"/> 10 <result property="pid" column="pid"/> 11 <collection property="children" ofType="cn.sohappy.acourses.bean.Category" select="findCategoriesByParentId" column="cid"/> 12 </resultMap> 13 <select id="findCategoriesByParentId" resultMap="selectCategoriesByPid"> 14 select * from category where pid=#{0} 15 </select> 16 <!--02.單次查詢--> 17 <resultMap id="MenuOneSQL" type="cn.sohappy.acourses.bean.Category" autoMapping="false"> 18 <id property="cid" column="cid"/> 19 <result property="cname" column="cname"/> 20 <result property="pid" column="pid"/> 21 </resultMap> 22 <select id="findAllCategories" resultMap="MenuOneSQL"> 23 select * from category 24 </select> 25 </mapper>
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 class test20170921 { 17 @Test 18 //自關聯實現無窮分類 19 public void selfCorrelation(){ 20 SqlSession session = MyBatisUtil.getSession(); 21 ICategoryDAO mapper = session.getMapper(ICategoryDAO.class); 22 List<Category> categories = mapper.findCategoriesByParentId(0L); 23 for (Category item :categories) { 24 System.out.println(item); 25 } 26 session.close(); 27 } 28 @Test 29 //Map集合實現無窮分類 30 public void InfiniteMenu(){ 31 SqlSession session = MyBatisUtil.getSession(); 32 ICategoryDAO mapper = session.getMapper(ICategoryDAO.class); 33 List<Category> categoriesClassified = new InfiniteMenuUtil().loadMenu(mapper.findAllCategories()); 34 for (Category item :categoriesClassified) { 35 System.out.println(item); 36 } 37 session.close(); 38 } 39 }
六、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 class InfiniteMenuUtil { 8 @SuppressWarnings("unchecked") 9 public <T> List<T> loadMenu(List<T> menus) { 10 List<T> rootMenus = new ArrayList<T>(); 11 if (menus != null && menus.size() != 0) { 12 List<Method> 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<Long, T> menuMap = new HashMap<Long, T>(); 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 List<T> ts; 60 try { 61 ts = (List<T>) 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 return rootMenus; 73 } 74 }