文章目录
- 1、开发需求中的树形结构
- 2、表结构设计
- 3、接口实现代码
- 模型类与接口定义
- Mapper层开发
1、开发需求中的树形结构
树形结构在日常开发中很常见,如:
再比如:
还有:
2、表结构设计
这种树形结构,其 核心字段为parentId
,即父节点id。先看上面课程信息树形结构的表设计:
精髓就是:每条数据,id是它自己的名字,parentId是它爹的名字。根据parentId能知道它爹是谁,而
它的id就是它儿子的parentId
,WHERE parentId = Id就知道了它的儿子是谁。
MySQL表结构设计如下:
字段名 | 数据类型 | 解释 | 是否必须 |
---|---|---|---|
id | varchar | 主键,唯一标识这条数据,也是它子节点的parentId | 是 |
name | varchar | 分类中文名称,以后要展示在前端的信息 | 是 |
parentId | varchar | 核心字段,父节点id,它爹的名字 | 是 |
is_show | tinyint | 控制这条数据是否显示,就是逻辑删除的那个味儿 | 根据需求分析是否加,像全国省市区,自然不用 |
orderby | int | 排序字段,同层的节点,返回时谁先谁后 | 看需求,对节点展示有顺序要求时用 |
is_leaf | tinyint | 是否叶子节点,1是0否 | 看需求,方便后端的一个字段 |
nodelevel | int | 层级标识字段 | 看需求,像省市区树形,这个字段可以标识下1省级2市级3区级 |
3、接口实现代码
模型类与接口定义
定义返回给前端的vo类,核心属性childrenTreeNodes
//伪代码
//假设树形结构表的PO类叫TreePo
@Data
public class TreeVo extends TreePo{
List<TreeVo> childrenTreeNodes;
}
//注意这里childrenTreeNodes类型为TreeVo,而不是TreePo,因为你儿子也有自己的儿子
随便定义个示意接口,免得突兀:
@Slf4j
@RestController
public class TreeInfocontroller{
@GetMapping("/tree/info/list")
public List<TreeVo> queryTreeNodes(){
return null;
}
}
Mapper层开发
这里以上面的行业分类树形表为例:
当树形结构的
层级固定,比如都只有两级,此时使用表的自联结查询即可完成
:
# 假设表名是t_tree
# pid即核心字段parentId
SELECT
one.id one_id,
one.name one_name,
one.pid one_pid,
two.id two_id,
two.name two_name,
two.pid two_pid
FROM t_tree one
INNER JOIN t_tree two
ON one.id = two.pid
WHERE one.pid='根节点id';
# 有一条无意义数据,叫根节点,其子节点就是前端页面的第一级数据
# 有排序字段的话继续order by one.orderbyField,two.orderbyField
这就查出来了前两级:
当树形结构层级不固定
,有的两级深、有的三级深,则应MySQL递归查询
WITH RECURSIVE tem_table AS(
SELECT * FROM t_tree one WHERE id='0'
UNION ALL
SELECT two.* FROM t_tree two INNER JOIN tem_table ON tem_table.id = two.pid
)
SELECT * FROM tem_table ;
# 有排序需求时后面继续order by tem_table.id......
- tem_table是一个表名
- 使用UNION ALL 不断将每次递归得到的数据加入到表tem_table中
- select * from t_tree p where id= '0’即tem_table表中的初始数据是id=0的记录,即根节点
- 通过inner join tem_table ON tem_table.id = two.pid 找到id='0’的下级节点
- 最后select * from tem_table拿递归得到的所有数据
以上是MySQL8.0的写法,再补一个MySQL5.7版本的递归写法