数据库树状结构的设计和处理以及Spring Boot中MyBatis对树状结构的级联操作

简介: 数据库树状结构的设计和处理以及Spring Boot中MyBatis对树状结构的级联操作

在实际开发中,我们发现,其实很多数据结构是树状的,每个节点下面有不确定数量的节点,并且深度也不确定。这种数据结构应当如何进行处理呢?

其实我们的文件目录,就是这样的数据结构:

网络异常,图片无法展示
|

那么今天就以一个设计和查询一个简单的目录为例来进行讲解。

1,设计数据库表和类

我们首先还是设计数据库和类。

简单起见,我们这里的目录类只有id和名字这两个基本信息。我们先设计数据库表如下:

网络异常,图片无法展示
|

可见除了基本信息以外,我还加了parent_id字段表示某个目录的上一级目录,即为它的父目录。借助这个字段,我们是不是就可以查到一个目录之下所有的子目录了呢?

好的,我们继续设计类图,构建的目录类如下:

网络异常,图片无法展示
|

在Java的类里面,我们就没有设定parent_id这个字段了,而是换成了子目录的集合。这样我们下面使用MyBatis进行级联查询到一个目录时,就直接把子目录放在这个集合即可。

这里给出目录表sql文件和类代码:

Java类:

packagecom.example.treehandle.dataobject;
importlombok.Getter;
importlombok.NoArgsConstructor;
importlombok.Setter;
importjava.io.Serializable;
importjava.util.List;
/*** 菜单类*/@Getter@Setter@NoArgsConstructorpublicclassMenuimplementsSerializable {
/*** 主键id*/privateintid;
/*** 目录名*/privateStringname;
/*** 该目录下的子目录*/privateList<Menu>childMenus;
}

sql文件:

-- 初始化表droptable if exists `menu`;createtable `menu`
(   `id`        intunsigned auto_increment,   `name`      varchar(16)notnull,   `parent_id` intnotnull,-- 这个目录的父目录id,如果这个目录是根目录那么这个字段值为0   primary key (`id`)) engine = InnoDB
  default charset = utf8mb4;-- 初始化测试数据insertinto `menu` (`name`, `parent_id`)values('音乐',0),('视频',0),('图片',0),('中文歌',1),-- “中文歌”目录是“音乐”的子目录('英文歌',1),-- “英文歌”目录是“音乐”的子目录('动物',3),-- “动物”目录是“图片”的子目录('二次元',3),-- “二次元”目录是“图片”的子目录('动漫',7),-- “动漫”目录是“二次元”的子目录('二次元游戏',7),-- “二次元游戏”目录是“二次元”的子目录('公主连结',9),-- “公主连结”目录是“二次元游戏”的子目录('碧蓝航线',9),-- “碧蓝航线”目录是“二次元游戏”的子目录('原神',9);-- “原神”目录是“二次元游戏”的子目录

那么重要的问题来了:怎么进行树状结构的级联查询呢?我们往下看。

2,MyBatis级联查询树状结构

首先还是定义DAO层,这里只写两个查询方法:

packagecom.example.treehandle.dao;
importcom.example.treehandle.dataobject.Menu;
importorg.apache.ibatis.annotations.Mapper;
importjava.util.List;
@MapperpublicinterfaceMenuDAO {
/*** 根据id查找目录*/MenugetById(intid);
/*** 根据父目录id查找目录(查找某一目录下的所有子目录)*/List<Menu>getByParentId(intparentId);
}

这里除了定义getById方法,我们还定义了getByParentId方法,这个就是用于帮助我们查到一个目录的子目录的方法。

然后就是编写MyBatis Mapper XML文件:

<?xmlversion="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mappernamespace="com.example.treehandle.dao.MenuDAO"><resultMapid="menuResultMap"type="com.example.treehandle.dataobject.Menu"><idcolumn="id"property="id"/><resultcolumn="name"property="name"/><!-- 查询以自身id为父节点的节点,实现往下递归查询 --><collectionproperty="childMenus"select="com.example.treehandle.dao.MenuDAO.getByParentId"column="id"fetchType="eager"/></resultMap><selectid="getById"resultMap="menuResultMap">      select *
      from `menu`
      where id = #{id}
</select><selectid="getByParentId"resultMap="menuResultMap">      select *
      from `menu`
      where parent_id = #{parentId}
</select></mapper>

这里是重点,在上面resultMap节点中,我们定义了collection节点表示我们的childMenus属性是个集合,这个collection节点中各个属性如下:

  • property 表示这个节点数据对应目录类中的哪个属性
  • select 指定执行一个DAO查询方法并将其结果放在该节点
  • column 用于执行select属性中查询方法的参数
  • fetchType 指定是懒获取还是全部获取

那么可见,我们在执行getById查询方法时,遇到这个collection节点,就会以查到的自己的id字段值作为参数去执行getByParentId查询方法,即查询以自身id为父目录id的目录(说白了就是查询自己的所有子目录),这样就实现了往下递归查询,这样就能查询到一个目录以及其所有子目录的信息了。

这里,我们就完成了对树状结构的设计和查询了!

编写一个接口并查询一下试试,结果如下:

网络异常,图片无法展示
|

完整结果:

{
"id": 3,
"name": "图片",
"childMenus": [
        {
"id": 6,
"name": "动物",
"childMenus": []
        },
        {
"id": 7,
"name": "二次元",
"childMenus": [
                {
"id": 8,
"name": "动漫",
"childMenus": []
                },
                {
"id": 9,
"name": "二次元游戏",
"childMenus": [
                        {
"id": 10,
"name": "公主连结",
"childMenus": []
                        },
                        {
"id": 11,
"name": "碧蓝航线",
"childMenus": []
                        },
                        {
"id": 12,
"name": "原神",
"childMenus": []
                        }
                    ]
                }
            ]
        }
    ]
}

可见,一个清晰明了的树状结构就查出来了。

示例仓库地址

相关文章
|
1天前
|
SQL XML Java
Spring5入门到实战------12、使用JdbcTemplate操作数据库(增删改查)。具体代码+讲解 【上篇】
这篇文章是Spring5框架的实战教程,详细讲解了如何使用JdbcTemplate进行数据库的增删改查操作,包括在项目中引入依赖、配置数据库连接池、创建实体类、定义DAO接口及其实现,并提供了具体的代码示例和测试结果,最后还提供了完整的XML配置文件和测试代码。
Spring5入门到实战------12、使用JdbcTemplate操作数据库(增删改查)。具体代码+讲解 【上篇】
|
4天前
|
SQL 数据库
Spring5入门到实战------13、使用JdbcTemplate操作数据库(批量增删改)。具体代码+讲解 【下篇】
这篇文章是Spring5框架的实战教程,深入讲解了如何使用JdbcTemplate进行数据库的批量操作,包括批量添加、批量修改和批量删除的具体代码实现和测试过程,并通过完整的项目案例展示了如何在实际开发中应用这些技术。
Spring5入门到实战------13、使用JdbcTemplate操作数据库(批量增删改)。具体代码+讲解 【下篇】
|
5天前
|
SQL JavaScript 前端开发
vue中使用分页组件、将从数据库中查询出来的数据分页展示(前后端分离SpringBoot+Vue)
这篇文章详细介绍了如何在Vue.js中使用分页组件展示从数据库查询出来的数据,包括前端Vue页面的表格和分页组件代码,以及后端SpringBoot的控制层和SQL查询语句。
vue中使用分页组件、将从数据库中查询出来的数据分页展示(前后端分离SpringBoot+Vue)
|
1天前
|
SQL 关系型数据库 MySQL
解决:Mybatis-plus向数据库插入数据的时候 报You have an error in your SQL syntax
该博客文章讨论了在使用Mybatis-Plus向数据库插入数据时遇到的一个常见问题:SQL语法错误。作者发现错误是由于数据库字段中使用了MySQL的关键字,导致SQL语句执行失败。解决方法是将这些关键字替换为其他字段名称,以避免语法错误。文章通过截图展示了具体的操作步骤。
|
18小时前
|
JavaScript Java Maven
毕设项目&课程设计&毕设项目:springboot+vue实现的在线求职管理平台(含教程&源码&数据库数据)
本文介绍了一款基于Spring Boot和Vue.js实现的在线求职平台。该平台采用了前后端分离的架构,使用Spring Boot作为后端服务
毕设项目&课程设计&毕设项目:springboot+vue实现的在线求职管理平台(含教程&源码&数据库数据)
|
4天前
|
前端开发 JavaScript Java
SpringBoot+Vue+token实现(表单+图片)上传、图片地址保存到数据库。上传图片保存位置自己定义、图片可以在前端回显(一))
这篇文章详细介绍了在SpringBoot+Vue项目中实现表单和图片上传的完整流程,包括前端上传、后端接口处理、数据库保存图片路径,以及前端图片回显的方法,同时探讨了图片资源映射、token验证、过滤器配置等相关问题。
|
4天前
|
前端开发 数据库
SpringBoot+Vue+token实现(表单+图片)上传、图片地址保存到数据库。上传图片保存位置到项目中的静态资源下、图片可以在前端回显(二))
这篇文章是关于如何在SpringBoot+Vue+token的环境下实现表单和图片上传的优化篇,主要改进是将图片保存位置从磁盘指定位置改为项目中的静态资源目录,使得图片资源可以跨环境访问,并在前端正确回显。
|
4天前
|
XML 数据库 数据格式
Spring5入门到实战------14、完全注解开发形式 ----JdbcTemplate操作数据库(增删改查、批量增删改)。具体代码+讲解 【终结篇】
这篇文章是Spring5框架的实战教程的终结篇,介绍了如何使用注解而非XML配置文件来实现JdbcTemplate的数据库操作,包括增删改查和批量操作,通过创建配置类来注入数据库连接池和JdbcTemplate对象,并展示了完全注解开发形式的项目结构和代码实现。
Spring5入门到实战------14、完全注解开发形式 ----JdbcTemplate操作数据库(增删改查、批量增删改)。具体代码+讲解 【终结篇】
|
4天前
|
SQL XML Java
Spring5入门到实战------12、使用JdbcTemplate操作数据库(增删改查)。具体代码+讲解 【上篇】
这篇文章是Spring5框架的实战教程,详细讲解了如何使用JdbcTemplate进行数据库的增删改查操作,包括在项目中引入依赖、配置数据库连接池、创建实体类、定义DAO接口及其实现,并提供了具体的代码示例和测试结果,最后还提供了完整的XML配置文件和测试代码。
Spring5入门到实战------12、使用JdbcTemplate操作数据库(增删改查)。具体代码+讲解 【上篇】
|
5天前
|
XML SQL JavaScript
在vue页面引入echarts,图表的数据来自数据库 springboot+mybatis+vue+elementui+echarts实现图表的制作
这篇文章介绍了如何在Vue页面中结合SpringBoot、MyBatis、ElementUI和ECharts,实现从数据库获取数据并展示为图表的过程,包括前端和后端的代码实现以及遇到的问题和解决方法。
在vue页面引入echarts,图表的数据来自数据库 springboot+mybatis+vue+elementui+echarts实现图表的制作