树型结构设计和实现(菜单树)
一、数据库设计
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS `tree`;
CREATE TABLE `devices_tree` (
`node_id` bigint(32) NOT NULL COMMENT '节点Id',
`parent_id` bigint(32) NOT NULL COMMENT '父节点ID',
`node_name` varchar(32) COMMENT '节点名称',
`node_type` int(2) COMMENT '节点类型',
`create_time` varchar(32) COMMENT '创建时间',
`remark` varchar(255) COMMENT '备注',
PRIMARY KEY (`node_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '树型表' ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
二、代码实现
在实体类加children字段
@ApiModelProperty(value = "所有子分类")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@TableField(exist = false)
private List<实体类> children;
public List<Tree> lisTree() {
List<实体类> entities = baseMapper.selectList(null);
List<实体类> collect = entities.stream().filter(tree ->
tree.getParentId() == 0
).map((menu) -> {
menu.setChildren(getChildren(menu, entities));
return menu;
}).collect(Collectors.toList());
return collect;
}
private List<Tree> getChildren(实体类 root, List<实体类> all) {
List<实体类> children = all.stream().filter(tree -> {
return tree.getParentId().longValue() == root.nodeId().longValue();
}).map(entity -> {
entity.setChildren(getChildren(entity, all));
return entity;
}).collect(Collectors.toList());
return children;
}
三、查找当前树下的 id数组
@Override
public List<Long> knowledgeIdLongList(Long id) {
List<Long> path = new ArrayList<>();
path.add(id);
List<Long> paths = this.findKnowledgeIdPath(id,path);
return paths;
}
private List<Long> findKnowledgeIdPath(Long id,List<Long> path) {
List<实体类> treeList = baseMapper.selectList(new QueryWrapper<实体类>().eq("parent_id", id));
if (treeList != null && treeList.size()>0) {
knowledgeTreeList.forEach(tree -> {
path.add(tree.getId());
this.findKnowledgeIdPath(tree.getId(),path);
});
}
return path;
}
在tree表中加一个字段,可解决这个循环遍历消耗内存和查询时间问题
ancestors varchar(50) default '' comment '祖级列表',
四、list集合转换为String以分号隔开
List<String> skuAttrValues;
String skuAttrValues = StringUtils.collectionToDelimitedString(skuAttrValues, ";");
|