MyBatis無限級分類實現的兩種方法--自關聯與map集合

一、這回先建立數據庫吧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 }
相關文章
相關標籤/搜索