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. SecureCRT 专题

    SecureCRT在同一窗口打开多个标签:选中“在标签页中打开”即可 SecureCRT同时向多个tab窗口发送相同的命令 Step by step: 作为管理N台服务器,而又要执行相同命令又不想用脚 ...

  2. 3D场景中的鼠标响应事件

    原文:3D场景中的鼠标响应事件 今天要讲的是3D场景中的鼠标响应事件的处理,首先Button的响应是大家熟知的,只要加上一个click事件,然后写一个响应的处理时间就行了.对于二维平面上的一些控件也很 ...

  3. OpenCV 图像清晰度评价(相机自动对焦)

    相机的自动对焦要求相机根据拍摄环境和场景的变化,通过相机内部的微型驱动马达,自动调节相机镜头和CCD之间的距离,保证像平面正好投影到CCD的成像表面上.这时候物体的成像比较清晰,图像细节信息丰富. 相 ...

  4. flash导出正常清晰(无色差)GIF图片

    前言: 这枚GIF算是半临摹作品.我使用的FLASH制作这个小动画,其实这类型的动画用AE做会更便捷. 进入主题前,先摆出个成品 教程结束,以上就是flash制作出来的小动画怎么导出正常清晰(无色差) ...

  5. Ubuntu+NDK编译openssl(为了Android上使用libcurl且支持HTTPS协议)

    为了Android上使用libcurl且支持HTTPS协议,需要依赖openssl,因此先来了解一下如何编译OpenSSL1.编译ARM下的共享库(默认的)我使用的是guardianproject的o ...

  6. hibernate关于一对一注解配置

    注解(Annotation),也叫元数据.一种代码级别的说明.它是JDK1.5及以后版本引入的一个特性,与类.接口.枚举是在同一个层次.它可以声明在包.类.字段.方法.局部变量.方法参数等的前面,用来 ...

  7. SAP HR工资配置项1---工资计算周期配置

    对于工资计算,三个方面需要配置:工资计算期.工资类型.工资. 下面是工资期内的配置: 1.在定义参数 在参数指示工资的频率. 主题 设置期间參数 菜单路径 SAP 用户化实施指南→工资核算→工资核算: ...

  8. android x86 7.0 32bit调试apk时出现的错误

    detected problems with app native libraries libavcodec.so:text relocationslibavutil.solibswresample. ...

  9. 【转】ORACLE AWR报告

    转自:http://blog.csdn.net/liqfyiyi/article/details/8236864 About Oracle AWR Oracle AWR is a powerful m ...

  10. uwp开发————换背景图片

    原文:uwp开发----换背景图片 用后台代码来实现对容器背景的切换,用本地图片作为背景. 把需要的图片素材放到Assets文件夹下 前台xaml代码如下: <Grid x:Name=" ...