MyBatis-plus如何实现树形结构展示

半城伤御伤魂 提交于 2020-08-14 02:12:28

一 提出需求
先看一下我们的需求,我们的需求是要实现下面这个页面的树形展示。使用的技术是MyBatis-plus。

二 分析需求
首先分析一下这个页面,这个页面是以树形结构的方式展示权限(资源)列表。虽然是树形展示,本质上,它还是一个表。我们可以这样定义权限(资源)表。



CREATE TABLE `sys_resource` (
  `id` varchar(30) NOT NULL,
  `name` varchar(50) NOT NULL,
  `parent_id` varchar(30) DEFAULT NULL,
  `type` int(1) NOT NULL DEFAULT '0',
  `url` varchar(100) DEFAULT NULL,
  `permission` varchar(50) DEFAULT NULL,
  `color` varchar(10) DEFAULT NULL,
  `icon` varchar(30) DEFAULT NULL,
  `sort` int(11) NOT NULL DEFAULT '0',
  `verification` tinyint(1) NOT NULL DEFAULT '0',
  `create_date` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

看上去,还是有点抽象,我们拿表数据说话。


我们分析一下这个表。其中绿色标识出来的是一级节点。红色标识出来的是二级节点,其它都是三级节点。一级节点和二级节点是通过parent_id进行关联,二级节点和三级节点也是通过parent_id进行关联。

关于不同级别节点的关联关系,上面这个表格看得不是太清楚。我们看下面这个图就比较清楚了。

我们需要关注的是12行的id列。19到21行,以及24到27行的parent_id列。也就是绿色标识的地方。这个是反映“用户管理”二级节点和三级节点的关系,它们是通过parent_id进行关联的。
数据库分析到这里,下面我们最后分析代码。
三 代码分析
这里给出最关键的二段代码。
1 查询入口函数





@Override
public List<SysResource> list() {
    EntityWrapper<SysResource> wrapper = new EntityWrapper<>();
    wrapper.eq("parent_id", 0)
            .or()
            .isNull("parent_id")
            .orderBy("sort");
    // 得到一级节点资源列表
    List<SysResource> resources = this.selectList(wrapper);
    if (resources != null && resources.size() > 0) {
        resources.forEach(this::findAllChild);
    }
    return resources;
}

2 递归查询函数findAllChild

public void findAllChild( SysResource resource ) {
    EntityWrapper<SysResource> wrapper = new EntityWrapper<>();
    wrapper.eq("parent_id", resource.getId()).orderBy("sort");
    // 首次进入这个方法时,查出的是二级节点列表
    // 递归调用时,就能依次查出三、四、五等等级别的节点列表,
    // 递归能实现不同节点级别的无限调用,这个层次不易太深,否则有性能问题
    List<SysResource> resources = this.selectList(wrapper);
    resource.setChildren(resources);
    if (resources != null && resources.size() > 0) {
        resources.forEach(this::findAllChild);
    }
}

这两段代码都用到了MyBatis-plus的功能,就是这样简洁,两段代码完成了树形结构的封装。注释在代码中写得很详细。
以“首页”这个节点为例,我们可以通过调试以及查数据库的方法跟踪一下过程。

第一步:查询一级节点语句以及结果如下

SELECT id AS id,`name`,parent_id AS parentId,`type`,url,permission,color,icon,sort,verification,create_date AS createDate
FROM sys_resource WHERE (parent_id = 0 OR parent_id IS NULL) ORDER BY sort
+---------------------+--------------+----------+------+-----------+------------+---------+------------------+------+--------------+---------------------+
| id                  | name         | parentId | type | url       | permission | color   | icon             | sort | verification | createDate          |
+---------------------+--------------+----------+------+-----------+------------+---------+------------------+------+--------------+---------------------+
| 987977834901315586  | 首页         | NULL     |    0 | /home     | home       | #19BE6B | ios-home-outline |   -1 |            1 | 2018-04-22 16:54:06 |
| 1259381996845158401 | 业务管理     | NULL     |    0 | /business | business   | #19BE6B |                  |    0 |            1 | 2020-05-10 15:16:21 |
| 987981277195968513  | 系统设置     | NULL     |    0 | /system   | system     | #19BE6B | ios-gear         |    0 |            1 | 2018-04-22 17:07:46 |
+---------------------+--------------+----------+------+-----------+------------+---------+------------------+------+--------------+---------------------+
3 rows in set (0.00 sec)

下面这个结果是调试时打印出的一级节点“首页”。

SysResource(id=987977834901315586, name=首页, parentId=null, type=0, url=/home, permission=home, color=#19BE6B, icon=ios-home-outline, sort=-1,
verification=true, createDate=Sun Apr 22 16:54:06 CST 2018, children=null)

第二步: 查询一级节点“首页”的二级节点语句以及结果如下

SELECT id AS id,`name`,parent_id AS parentId,`type`,url,permission,color,icon,sort,verification,create_date AS createDate
FROM sys_resource WHERE (parent_id = '987977834901315586') ORDER BY sort ;
+---------------------+--------+--------------------+------+-------------+------------+---------+------+------+--------------+---------------------+
| id                  | name   | parentId           | type | url         | permission | color   | icon | sort | verification | createDate          |
+---------------------+--------+--------------------+------+-------------+------------+---------+------+------+--------------+---------------------+
| 1001315563194589185 | 首页   | 987977834901315586 |    0 | /home/index | home_index | #19BE6B |      |    0 |            0 | 2018-05-29 12:13:28 |
+---------------------+--------+--------------------+------+-------------+------------+---------+------+------+--------------+---------------------+
1 row in set (0.00 sec)

注意结果中此首页非彼首页,虽然名字一样,但完全是两条不同的记录。注意id号不一样哦。

下面这个结果是调试时打印出的二级节点“首页”,二级节点“首页”很惨,没有孩子。

SysResource(id=1001315563194589185, name=首页, parentId=987977834901315586, type=0, url=/home/index, permission=home_index, color=#19BE6B, icon=, sort=0,
verification=false, createDate=Tue May 29 12:13:28 CST 2018, children=null)

第三步:查询二级“首页”节点的三级节点语句以及结果如下

SELECT id AS id,`name`,parent_id AS parentId,`type`,url,permission,color,icon,sort,verification,create_date AS createDate
FROM sys_resource WHERE (parent_id = '1001315563194589185') ORDER BY sort
Empty set (0.00 sec)

查询结果为空,因为二级“首页”根本就没三级节点。
分析到这里,就算完了,大家好好揣摩一下,也可试着调试下代码。

最后再看一下封装后返回的resources到底长得怎么样。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!