多级分类(树形结构)数据解决方案
多级分类(树形结构)数据解决方案
1.需求说明
在日常开发中多级分类、多级栏目、数据字典等需求,是我们经常会遇到的问题。需求的难点在于表结构的设计以及数据结构数据的封装。
- 需求图解
2.表结构设计
表字段说明
1.这里以家居分类为例,当然在实际开发中表字段会有一些差异。但只要是多级的树形结构我们通常都会根据parant_id去区分。
2.cat_level表示所属级别,返回给前端方便前端对父级和子级进行增删的判断,比如只允许1、2级别的分类进行添加操作;只允许最内层的分类进行删除操作。
3.is_show是否展示改分类、也可以用is_delete做逻辑删除来实现。
4.sort排序,如果由对分类排序需求可以根据改字段进行排序,如果没有则默认根据添加的先后顺序进行排序。
CREATE TABLE `commodity_category` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` char(50) NOT NULL COMMENT '名称',
`parent_id` bigint(20) NOT NULL COMMENT '父分类 id',
`cat_level` int(11) NOT NULL COMMENT '层级',
`is_show` tinyint(4) NOT NULL COMMENT '0 不显示,1 显示]',
`sort` int(11) NOT NULL COMMENT '排序',
`icon` char(255) NOT NULL COMMENT '图标',
`pro_unit` char(50) NOT NULL COMMENT '统计单位',
`pro_count` int(11) NOT NULL COMMENT '商品数量',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=653 DEFAULT CHARSET=utf8mb4 COMMENT='商品分类表';
3.代码实现
1.分类树形结构接口
CategoryController
/**
* 分类树形结构
* @return
*/
@RequestMapping("/list/tree")
public R listTree() {
List<CategoryEntity> entities = categoryService.listTree();
return R.ok().put("data", entities);
}
2.核心业务实现
实现思路:
1.查找出所有的一级分类集合
2.遍历一级分类,查找子级分类并利用递归查找子级下的子级分类逐级设置数据
3.返回带有层级关系的数据
CategoryService
//返回所有分类及其子分类(带有层级关系,树形结构)
List<CategoryEntity> listTree();
CategoryServiceImpl
/**
* 返回所有分类及其子分类(带有层级关系,树形结构)
*
* @return
*/
@Override
public List<CategoryEntity> listTree() {
//1.查询出所有数据
List<CategoryEntity> entities = baseMapper.selectList(null);
//2.组装成树形结构
List<CategoryEntity> categoryTree = entities.stream().filter(categoryEntity -> {
//2.1进行过滤,返回一级分类
return categoryEntity.getParentId() == 0;
}).map(category -> {
//2.2进行map映射操作,给每个分类设置对应的子分类(这个过程会使用到递归)
category.setChildrenCategories(getChildrenCategories(category, entities));
return category;
}).sorted((category1, category2) ->
(category1.getSort() == null ? 0 : category1.getSort()) - (category2.getSort() == null ? 0 : category2.getSort()))
.collect(Collectors.toList());
//3.返回带有层级关系的数据
return categoryTree;
}
/**
* 该方法的任务就是将root下的所有分类的层级关系组织好(有多少级就处理多少级),并返回
* 1.得到分类下的所有子分类
* 2.递归操作得到子分类下的子分类
* 3.进行排序返回
* 4.递归结束的方向是朝着,找到root这个一级分类下的所有子分类去结束的
* @param root
* @param all
* @return
*/
private List<CategoryEntity> getChildrenCategories(CategoryEntity root, List<CategoryEntity> all) {
List<CategoryEntity> childrenCategories = all.stream()
.filter(categoryEntity -> categoryEntity.getParentId().equals(root.getId()))
.map(categoryEntity -> {
categoryEntity.setChildrenCategories(getChildrenCategories(categoryEntity, all));
return categoryEntity;
}).sorted(Comparator.comparingInt(category -> (category.getSort() == null ? 0 : category.getSort())))
.collect(Collectors.toList());
return childrenCategories;
}
3.持久层采用mybatisplus实现,也可以使用写sql语句进行实现