zoukankan      html  css  js  c++  java
  • MyBatis无限级分类实现的两种方法--自关联与map集合

    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 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 }

    3、写接口:

    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 }

    4、小配置:

     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 }

    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 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 }
  • 相关阅读:
    网页包抓取工具Fiddler工具简单设置
    django-Celery分布式队列简单使用
    django-nginx与uwsgi项目部署
    mysql数据库备份之主从同步配置
    mysql开启二进制日志
    python-django框架中使用七牛云
    python-django框架中使用FastDFS分布式文件系统
    python-django框架中使用docker和elasticsearch配合实现搜索功能
    C#_WPF中创建二维码、识别二维码
    读书笔记:《企业IT架构转型之道-阿里巴巴中台战略思想与架构实战》
  • 原文地址:https://www.cnblogs.com/tomasman/p/7581667.html
Copyright © 2011-2022 走看看