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. 微软输入法TSF SampleIME 代码浅说

    原文:微软输入法TSF SampleIME 代码浅说 微软提供了一个简单的TSF拼音输入法的示例SampleIME,主要的问题是:不支持数字键选候选字,不能自动上屏,没有联想功能.在笔者开发动态输入法 ...

  2. vim for windows download and installation

    这是vim皇冠vim简要 ------------------------------------------------- WHAT IS VIM Vim is an almost compatib ...

  3. MySQL 日期时间 专题

    1.1 获得当前日期+时间(date + time)函数:now() 除了 now() 函数能获得当前的日期时间外,MySQL 中还有下面的函数: current_timestamp()   curr ...

  4. LeapMotion Demo3

    原文:LeapMotion Demo3   从Github及其他论坛下载一些LeapMotion的例子,部分例子由于SDK的更新有一些小Bug, 已修复,感兴趣的可以下载:       http:// ...

  5. ASP .NET Views文件夹下面的文件找不到

    习惯将页面和它对应的js,css文件放在一个文件夹下,将这些都放在Views文件夹下     运行的时候发现找不到js和css文件 因为在MVC中,是不建议直接去访问Views文件夹的我们建立的ASP ...

  6. XF 列表视图绑定集合

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...

  7. 基于 CSP 的设计思想和 OOP 设计思想的异同

    LinkerLin Go语言推崇的CSP编程模型和设计思想,并没有引起很多Go开发者包括Go标准库作者的重视.标准库的很多设计保留了很浓的OOP的味道.本篇Blog想比较下从设计的角度看,CSP和OO ...

  8. php判断是否是移动设备

    function isMobile() { // 如果有HTTP_X_WAP_PROFILE则一定是移动设备 if (isset($_SERVER['HTTP_X_WAP_PROFILE'])) { ...

  9. .NET与Java互通AES算法加密解密

    /// <summary>AES加密</summary> /// <param name="text">明文</param> /// ...

  10. Win8 Metro(C#)数字图像处理--2.53图像傅立叶变换

    原文:Win8 Metro(C#)数字图像处理--2.53图像傅立叶变换  [函数名称] 1,一维FFT变换函数         Complex[] FFT(Complex[] sourceDat ...