1、这回先创建数据库吧

下表cid是CategoryId的缩写,cname是CategoryName的缩写,pid是parentId的缩写

无限级分类一般都包含这三个属性,至少也要包含cid和pid才能建立无限级关联

ok,这个东东就是无限级分类了。

即便是外行人稍微看一眼也能发现cid为1的图书在小说和周刊两行中作为了pid,也就是说小说和周刊的父级分类就是图书

图书和饮料的pid是0,代表他们是顶级分类

如果没有其他约束条件,这张表几乎可以无限向下级延伸,是一个树形结构,这里就不写什么数学公式了,道理很简单。想必大家都懂了。

2、写个实体类

首先还是生产实体类,植入一个他本身的List集合:

 package cn.sohappy.acourses.bean;

 import java.util.ArrayList;
import java.util.List; public class Category {
private Long cid;
private String cname;
private Long pid;
private List<Category> children; //省略getter and setter
}

然后初始化children并重写toString方法方便测试,完整代码如下:

 package cn.sohappy.acourses.bean;

 import java.util.ArrayList;
import java.util.List; public class Category {
private Long cid;
private String cname;
private Long pid;
private List<Category> children=new ArrayList<Category>();//这里为了防止后面空指针,初始化了children实例 public List<Category> getChildren() {
return children;
} public void setChildren(List<Category> children) {
this.children = children;
} public Long getCid() {
return cid;
} public void setCid(Long cid) {
this.cid = cid;
} public String getCname() {
return cname;
} public void setCname(String cname) {
this.cname = cname;
} public Long getPid() {
return pid;
} public void setPid(Long pid) {
this.pid = pid;
} @Override
public String toString() {
return "Category{cid:"+cid+
",cname:"+cname+
",pid:"+pid+
",children:"+children+
"}";
}
}

3、写接口:

List<Category> findCategoriesByParentId(Long pid);自关联查询

List<Category> findAllCategories();一条sql查询所有,后期用Map算法分级
 package cn.sohappy.acourses.course0921;

 import cn.sohappy.acourses.bean.Category;

 import java.util.List;

 public interface ICategoryDAO {
List<Category> findCategoriesByParentId(Long pid);
List<Category> findAllCategories();
}

4、小配置:

 <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.sohappy.acourses.course0921.ICategoryDAO">
<!--.自关联查询-->
<resultMap id="selectCategoriesByPid" type="cn.sohappy.acourses.bean.Category">
<id property="cid" column="cid"/>
<result property="cname" column="cname"/>
<result property="pid" column="pid"/>
<collection property="children" ofType="cn.sohappy.acourses.bean.Category" select="findCategoriesByParentId" column="cid"/>
</resultMap>
<select id="findCategoriesByParentId" resultMap="selectCategoriesByPid">
select * from category where pid=#{}
</select>
<!--.单次查询-->
<resultMap id="MenuOneSQL" type="cn.sohappy.acourses.bean.Category" autoMapping="false">
<id property="cid" column="cid"/>
<result property="cname" column="cname"/>
<result property="pid" column="pid"/>
</resultMap>
<select id="findAllCategories" resultMap="MenuOneSQL">
select * from category
</select>
</mapper>

5.测试类:

 package cn.test;

 import cn.sohappy.acourses.bean.BillManyToOne;
import cn.sohappy.acourses.bean.Category;
import cn.sohappy.acourses.bean.UserOneToMany;
import cn.sohappy.acourses.course0921.ICategoryDAO;
import cn.sohappy.acourses.course0921.IUserDAO;
import cn.sohappy.acourses.course0921.InfiniteMenuUtil;
import cn.sohappy.bean.Smbms_user;
import cn.sohappy.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test; import java.util.List; public class test20170921 {
@Test
//自关联实现无穷分类
public void selfCorrelation(){
SqlSession session = MyBatisUtil.getSession();
ICategoryDAO mapper = session.getMapper(ICategoryDAO.class);
List<Category> categories = mapper.findCategoriesByParentId(0L);
for (Category item :categories) {
System.out.println(item);
}
session.close();
}
@Test
//Map集合实现无穷分类
public void InfiniteMenu(){
SqlSession session = MyBatisUtil.getSession();
ICategoryDAO mapper = session.getMapper(ICategoryDAO.class);
List<Category> categoriesClassified = new InfiniteMenuUtil().loadMenu(mapper.findAllCategories());
for (Category item :categoriesClassified) {
System.out.println(item);
}
session.close();
}
}

6、InfiniteMenu的Map算法

 package cn.sohappy.acourses.course0921;

 import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*; public class InfiniteMenuUtil {
@SuppressWarnings("unchecked")
public <T> List<T> loadMenu(List<T> menus) {
List<T> rootMenus = new ArrayList<T>();
if (menus != null && menus.size() != ) {
List<Method> methodsList = Arrays.asList(menus.get().getClass().getDeclaredMethods());
//这里可以自己定制啦,我定制的是以pid,id,children结尾的get方法为分别getPid,getId,getChildren.所以menu类(Category)的属性名要符合定制规范
Method getId = null;
Method getPid = null;
Method getChildren = null;
//get getMethod
for (Method item : methodsList) {
if ("get".equals(item.getName().toLowerCase().substring(,))&&item.getName().length()>=&&"pid".equals(item.getName().toLowerCase().substring(item.getName().length() - , item.getName().length()))){
getPid = item;
continue;
}
if ("get".equals(item.getName().toLowerCase().substring(,))&&item.getName().length()>=&&"id".equals(item.getName().toLowerCase().substring(item.getName().length() - , item.getName().length()))){
getId = item;
continue;
}
if ("get".equals(item.getName().toLowerCase().substring(,))&&item.getName().length()>=&&"children".equals(item.getName().toLowerCase().substring(item.getName().length() - , item.getName().length()))){
getChildren = item;
}
}
if (getId!=null&&getPid!=null&&getChildren!=null){
//get menuMap
Map<Long, T> menuMap = new HashMap<Long, T>();
for (T menu : menus) {
Long id = null;
try {
id = (Long)getId.invoke(menu);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
menuMap.put(id,menu);
}
//add children
for (T menu:menus) {
Long pid = null;
try {
pid = (Long)getPid.invoke(menu);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
if (pid==null||pid==){
rootMenus.add(menu);
}else {
T t = menuMap.get(pid);
List<T> ts;
try {
ts = (List<T>) getChildren.invoke(t);
ts.add(menu);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
return rootMenus;
}
}

MyBatis无限级分类实现的两种方法--自关联与map集合的更多相关文章

  1. 【mybatis基础】mybatis开发dao两种方法

    mybatis是一个支持普通SQL查询,存储过程和高级映射的优秀的持久层的框架,是apache下的顶级项目.mybatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.mybat ...

  2. mybatis 根据id批量删除的两种方法

    原文:https://blog.csdn.net/qq_40010745/article/details/81032218 mybatis 根据id批量删除的两种方法   第一种,直接传递给mappe ...

  3. 使用PHP发送邮件的两种方法

    使用PHP发送邮件的两种方法 May242013 作者:Jerry Bendy   发布:2013-05-24 22:25   分类:PHP   阅读:2,107 views   抢沙发     今天 ...

  4. C++调用DLL有两种方法——静态调用和动态调用

    C++调用DLL有两种方法——静态调用和动态调用 标签: dllc++winapinullc 2011-09-09 09:49 11609人阅读 评论(0) 收藏 举报  分类: cpp(30)  [ ...

  5. Delphi Windows API判断文件共享锁定状态(OpenFile和CreateFile两种方法)

    一.概述 锁是操作系统为实现数据共享而提供的一种安全机制,它使得不同的应用程序,不同的计算机之间可以安全有效地共享和交换数据.要保证安全有效地操作共享数据,必须在相应的操作前判断锁的类型,然后才能确定 ...

  6. 原生Js 两种方法实现页面关键字高亮显示

    原生Js 两种方法实现页面关键字高亮显示 上网看了看别人写的,不是兼容问题就是代码繁琐,自己琢磨了一下用两种方法都可以实现,各有利弊. 方法一 依靠正则表达式修改 1.获取obj的html2.统一替换 ...

  7. 取xml文件转成List<T>对象的两种方法

    读取xml文件转成List<T>对象的两种方法(附源码)   读取xml文件转成List<T>对象的两种方法(附源码) 读取xml文件,是项目中经常要用到的,所以就总结一下,最 ...

  8. oracle rename数据文件的两种方法

    oracle rename数据文件的两种方法 2012-12-11 20:44 10925人阅读 评论(0) 收藏 举报  分类: oracle(98)  版权声明:本文为博主原创文章,未经博主允许不 ...

  9. MyBatis开发Dao层的两种方式(原始Dao层开发)

    本文将介绍使用框架mybatis开发原始Dao层来对一个对数据库进行增删改查的案例. Mapper动态代理开发Dao层请阅读我的下一篇博客:MyBatis开发Dao层的两种方式(Mapper动态代理方 ...

随机推荐

  1. C++:怎样把一个int转成4个字节?

    大家都知道,一个int 或 unsigned int是由4个字节组成的,(<C/C++学习指南>,第3章,第3.2.3节:变量的内存视图) 比如, int   n  =  sizeof( ...

  2. WPF:将Office文档、任意类型文件嵌入到EXE可执行文件中

    原文:WPF:将Office文档.任意类型文件嵌入到EXE可执行文件中 版权声明:本文为博主原创文章,未经博主允许可以随意转载 https://blog.csdn.net/songqingwei198 ...

  3. UVA10940 - Throwing cards away II(找到规律)

    UVA10940 - Throwing cards away II(找规律) 题目链接 题目大意:桌上有n张牌,依照1-n的顺序从上到下,每次进行将第一张牌丢掉,然后把第二张放到这叠牌的最后.重复进行 ...

  4. 关于 IIS 上运行 ASP.NET Core 站点的“HTTP 错误 500.19”错误

    昨天回答了博问中的一个问题 —— “HTTP 错误 500.19 - Internal Server Error dotnetcore”,今天在这篇随笔中时候事后诸葛亮地小结一下. 服务器是 Wind ...

  5. js如何通过变量调用函数,函数名在变量里面

    js如何通过变量调用函数,函数名在变量里面. 有时候函数名是动态定义的,这时候我们就需要用到这个方法了. //赋值函数名称 var a = "b"; //定义函数 function ...

  6. MQTT开源代理Mosquitto源码分析(访问控制篇)

    一.整体流程概览 从GitHub下载源码后,代理的源码在src中,同时还用到了lib库中的一些函数.对项目的工作流程有个大概理解是分析mosquitto的访问控制权限的基础,网络上已有很多中文博客在介 ...

  7. PHPEXCEL 不能输出中文内容,只显示空白

    以他带的示例文件为例 01simple-download-xls.php // Add some data $objPHPExcel->setActiveSheetIndex(0)        ...

  8. 提示要求用户名和密码-localhost

    同时安装了tomcat和oracle9i后,调试jsp出现--连接到localhost 提示:位于 XDB 的服务器 localhost 要求用户名和密码,原因是端口冲突,调整如下. 机器上装了ora ...

  9. Windows Phone Launcher class

    Starts the default app associated with the specified file or URI. Launch a file contained in the app ...

  10. Android零基础入门第31节:几乎不用但要了解的AbsoluteLayout绝对布局

    原文:Android零基础入门第31节:几乎不用但要了解的AbsoluteLayout绝对布局 前面几期基本学习了Android开发中常用的四种布局,之所以把AbsoluteLayout放在后面来学习 ...