兩個字段:
- pid:父級ID
- parent_ids:所有經過的路徑節點ID
這樣設計有個好處是,可以查任意節點的所有子節點,從任意節點開始既可以向上查,也可以向下查
select * from enterprise where find_in_set(4, parent_ids);
構造菜單樹(Java實現)
@Data
@NoArgsConstructor
public class Menu {
private Integer id;
private Integer pid; // 父菜單ID
private String pids; // 所有父菜單ID集合(按順序,逗號分隔)
private String name;
private String code;
private int sort;
List<Menu> children;
public Menu(Integer id, Integer pid, String name, int sort) {
this.id = id;
this.pid = pid;
this.name = name;
this.sort = sort;
}
}
第一種寫法
@Test
void contextLoads() throws Exception {
List<Menu> allMenuList = new ArrayList<>();
allMenuList.add(new Menu(1, 0, "一級菜單A", 1));
allMenuList.add(new Menu(2, 0, "一級菜單B", 2));
allMenuList.add(new Menu(3, 1, "二級菜單AA", 1));
allMenuList.add(new Menu(4, 2, "二級菜單BB", 1));
allMenuList.add(new Menu(5, 3, "三級菜單AAA", 2));
allMenuList.add(new Menu(6, 4, "三級菜單BBB", 2));
allMenuList.add(new Menu(7, 1, "二級菜單AC", 2));
// 找到所有一級菜單
List<Menu> parentList = allMenuList.stream().filter(e->e.getPid().equals(0)).collect(Collectors.toList());
for (Menu menu : parentList) {
menu.setChildren(getChild(menu.getId(), allMenuList));
}
}
/**
* 遞歸查找子菜單
*/
public List<Menu> getChild(Integer pid, List<Menu> allMenuList) {
List<Menu> childList = new ArrayList<>();
for (Menu menu : allMenuList) {
if (pid.equals(menu.getPid())) {
menu.setChildren(getChild(menu.getId(), allMenuList));
childList.add(menu);
}
}
childList.sort(Comparator.comparing(Menu::getSort).reversed());
return childList;
}
第二種寫法
@Test
void contextLoads() throws Exception {
List<Menu> allMenuList = new ArrayList<>();
allMenuList.add(new Menu(1, 0, "一級菜單A", 1));
allMenuList.add(new Menu(2, 0, "一級菜單B", 2));
allMenuList.add(new Menu(3, 1, "二級菜單AA", 1));
allMenuList.add(new Menu(4, 2, "二級菜單BB", 1));
allMenuList.add(new Menu(5, 3, "三級菜單AAA", 2));
allMenuList.add(new Menu(6, 4, "三級菜單BBB", 2));
allMenuList.add(new Menu(7, 1, "二級菜單AC", 2));
// 第二種寫法
List<Menu> list = allMenuList.stream()
.filter(e->e.getPid().equals(0))
.peek(e->e.setChildren(getChild2(e.getId(), allMenuList)))
.sorted(Comparator.comparing(Menu::getSort))
.collect(Collectors.toList());
}
/**
* 遞歸查找子菜單(簡寫版)
*/
public List<Menu> getChild2(Integer pid, List<Menu> allMenuList) {
return allMenuList.stream()
.filter(e->pid.equals(e.getPid()))
.peek(e->e.setChildren(getChild2(e.getId(), allMenuList)))
.sorted(Comparator.comparing(Menu::getSort))
.collect(Collectors.toList());
}