递归查询子分类
递归查询子分类
电商平台比如京东和淘宝中,商品一般分三级菜单。要想实现一个接口查询一个商品的分类及其子分类信息,需要使用到递归查询。
数据表中的记录都是单条并且没有层级的,要想描述各个记录之间的层级父子关系,一般会设计一个 parentId
字段。
CREATE TABLE `t_category` (
`cat_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '分类id',
`name` char(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分类名称',
`parent_cid` bigint(20) NULL DEFAULT NULL COMMENT '父分类id',
`cat_level` int(11) NULL DEFAULT NULL COMMENT '层级',
`show_status` tinyint(4) NULL DEFAULT NULL COMMENT '是否显示[0-不显示,1显示]',
`sort` int(11) NULL DEFAULT NULL COMMENT '排序',
`icon` char(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图标地址',
`product_unit` char(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '计量单位',
`product_count` int(11) NULL DEFAULT NULL COMMENT '商品数量',
PRIMARY KEY (`cat_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1433 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '商品三级分类' ROW_FORMAT = Dynamic;
数据:
下面简述查询所有商品分类及其子分类的接口。
实体类:CategoryEntity
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import lombok.Data;
@Data
@TableName("t_category")
public class CategoryEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 分类id
*/
@TableId
private Long catId;
/**
* 分类名称
*/
private String name;
/**
* 父分类id
*/
private Long parentCid;
/**
* 层级
*/
private Integer catLevel;
/**
* 是否显示[0-不显示,1显示]
*/
private Integer showStatus;
/**
* 排序
*/
private Integer sort;
/**
* 图标地址
*/
private String icon;
/**
* 计量单位
*/
private String productUnit;
/**
* 商品数量
*/
private Integer productCount;
@TableField(exist = false)
private List<CategoryEntity> children;
}
为了表示子菜单,这里添加一个数据表中不存在的字段 children
,并且使用注解标识。
接口:
/**
* 查出所有分类以及子分类,以树形结构组装起来
*/
public List<CategoryEntity> listWithTree() {
// 1. 查出所有分类
List<CategoryEntity> entities = baseMapper.selectList(null);
// 2. 组装成父子的树形结构
// 2.1 找到所有的一级分类
List<CategoryEntity> level1Menus = entities.stream().filter(categoryEntity ->
categoryEntity.getParentCid() == 0
).map(menu -> {
// 2.2 设置子菜单
menu.setChildren(getChildren(menu, entities));
return menu;
// 2.3 排序
}).sorted(Comparator.comparingInt(menu -> (menu.getSort() == null ? 0 : menu.getSort())))
.collect(Collectors.toList());
return level1Menus;
}
/**
* 递归查找所有菜单的子菜单
*/
private List<CategoryEntity> getChildren(CategoryEntity root, List<CategoryEntity> all) {
List<CategoryEntity> children = all.stream().filter(categoryEntity ->
categoryEntity.getParentCid() == root.getCatId()
).map(categoryEntity -> {
// 1. 找到子菜单
categoryEntity.setChildren(getChildren(categoryEntity, all));
return categoryEntity;
}).sorted(Comparator.comparingInt(menu -> (menu.getSort() == null ? 0 : menu.getSort()))).collect(Collectors.toList());
return children;
}
前端数据效果:
这个模型有递归查询的接口中经常用到。
转载请注明作者和出处。