MySQL树形结构(多级菜单)的数据库表设计和查询
概述
想必下面的树形菜单大家都见过,但是是如何实现的,你们有没有想过?说下我是怎么想起设计这个东西的,在一个惠风和畅,风和日丽的午后,我盯着眼前已完成的项目陷入沉思,良久,我将树形菜单的每一级菜单都设计成为了单独的表,正准备写接口将所有的菜单都返回的时候,带我的哥哥给我讲了一遍树形菜单的结构与数据库如何设计,我又再一次陷入了沉思,现在反思一下可能是当时脑子很乱连递归这个基本的思想都有些难以理解了吧。
数据库的设计
其实简单来讲就是为每个菜单栏在添加一个parent_id字段,记录着自己父菜单的ID,以下面的菜单为例,我给出了对应数据库简单的设计,想必你一看就明白了。
树形菜单的查询
数据库的设计虽然已经完成了,但是我们如何实现查询呢?前端需要的是我们返回的树状菜单结构,那么我们自然需要一个对象去封装一下,在这里运用一下面向对象的思想考虑一下这个返回的对象要怎么封装吧
继续浏览查找答案吧。
1.封装返回结果对象Menu
@Data
public class Menu {
@ApiModelProperty("该菜单ID")
private Integer id;
@ApiModelProperty("该菜单的名称")
private String name;
@ApiModelProperty("该菜单的父菜单的ID")
private Integer parentId;
@ApiModelProperty("该菜单是否可见")
private Integer status;
@ApiModelProperty("该菜单的类型")
private String type;
@ApiModelProperty("该菜单创建时间")
private Date createTime;
@ApiModelProperty("该菜单最后作出修改操作的时间")
private Date updateTime;
@ApiModelProperty("该菜单所有的子菜单")
private List<Menu> childMenu;
2.编写根据ID查找菜单的SQL
@Mapper
@Repository
public interface MenuMapper extends BaseMapper<Menu> {
@Select("select id,name,type,parent_id,status from menu where parent_id = #{id}")
List<Menu> menuList(Integer id);
3.递归查询所有的菜单
@Override
public List<CategoryEntity> listWithTree() {
// 查询出所有分类
List<CategoryEntity> cs = this.getBaseMapper().selectList(null);
// 筛选出所有一级分类
return cs.stream()
.filter(categoryEntity -> categoryEntity.getParentCid() == 0L)
.peek(categoryEntity -> categoryEntity.setChildren(this.listChildren(categoryEntity,cs)))
.sorted(Comparator.comparing(CategoryEntity::getSort))
.collect(Collectors.toList());
private List<CategoryEntity> listChildren(CategoryEntity category,List<CategoryEntity> cs){
// 递归查找子分类
return cs.stream()