最近做一个网上的在线教育项目涉及树形结构数据展示,教程里使用建多个实体类分别查询并封装来展示,这样做对于两级树形结构还好说,如果对于多层树形结构来看就不太合适了。这里我用的是递归查询来展示,记录一下。
1.先贴图excel数据(这里通过excel录入表数据,只使用了三层结构,多层也适用):
表数据(parent_id为0的是一级分类,顶层数据):
2.对应实体类表数据实体类:
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="EduSubject对象", description="课程科目")
public class EduSubject implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "课程类别ID")
@TableId(value = "id", type = IdType.ID_WORKER_STR)
private String id;
@ApiModelProperty(value = "类别名称")
private String title;
@ApiModelProperty(value = "父ID")
private String parentId;
@ApiModelProperty(value = "排序字段")
private Integer sort;
@ApiModelProperty(value = "创建时间")
@TableField(fill = FieldFill.INSERT)
private Date gmtCreate;
@ApiModelProperty(value = "更新时间")
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date gmtModified;
}
3.返回页面的实体类vo
@Data
@NoArgsConstructor
@AllArgsConstructor
public class EduSubjectVo {
private String id;
private String parentId;
private String title;
private List<EduSubjectVo> children;
}
4.Controller接口,service接口
@ApiOperation(value = "查询分类树形列表")
@PostMapping("/findSubjectTreeList")
public JsonResult findSubjectTreeList() {
List<EduSubjectVo> eduSubjectVoList = eduSubjectService.findSubjectTreeList();
return JsonResult.success(eduSubjectVoList);
}
List<EduSubjectVo> findSubjectTreeList();
5.实现类核心方法
@Override
public List<EduSubjectVo> findSubjectTreeList() {
// 最终返回结果
List<EduSubjectVo> resultList = new ArrayList<>();
// 查询所有课程分类并转换
List<EduSubjectVo> allSubjectVoList = new ArrayList<>();
List<EduSubject> list = this.list(null);
for (EduSubject eduSubject : list) {
EduSubjectVo eduSubjectVo = new EduSubjectVo();
BeanUtils.copyProperties(eduSubject, eduSubjectVo);
allSubjectVoList.add(eduSubjectVo);
}
// 过滤一级分类
for (EduSubjectVo subjectVo : allSubjectVoList) {
if (Objects.deepEquals(subjectVo.getParentId(), "0")) {
getChildSubjectList(subjectVo, allSubjectVoList);
resultList.add(subjectVo);
}
}
return resultList;
}
private void getChildSubjectList(EduSubjectVo eduSubjectVo, List<EduSubjectVo>
eduSubjectVoList) {
// 过滤子节点,如果子节点不为空,开始递归查询所有节点,直到子节点为空停止
List<EduSubjectVo> children = eduSubjectVoList.stream().filter(e -> Objects.deepEquals(e.getParentId(), eduSubjectVo.getId())).collect(Collectors.toList());
if (!CollectionUtils.isEmpty(children)) {
for (EduSubjectVo child : children) {
getChildSubjectList(child, eduSubjectVoList);
}
eduSubjectVo.setChildren(children);
}
}
这样就一次递归查询出所有树形数据并封装返回了
6.页面渲染效果
7.小结
对于分层结构多但是数据量不是很大的情况下,可以用递归查询这种方式,简便快捷,不存在什么效率问题。但是对于数据量大且分层又多的情况,这种就不是很合适了(效率会比较低),这种情况就适合用懒加载的方式查询和渲染,即点一层调一次查询。