递归查询子分类

Posted itzhouq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了递归查询子分类相关的知识,希望对你有一定的参考价值。

递归查询子分类

电商平台比如京东和淘宝中,商品一般分三级菜单。要想实现一个接口查询一个商品的分类及其子分类信息,需要使用到递归查询。

技术图片

数据表中的记录都是单条并且没有层级的,要想描述各个记录之间的层级父子关系,一般会设计一个 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;
}

前端数据效果:

技术图片

这个模型有递归查询的接口中经常用到。

以上是关于递归查询子分类的主要内容,如果未能解决你的问题,请参考以下文章

php递归无限极分类怎么弄

oracle 递归 通过子节点查询根节点

Think PHP递归获取所有的子分类的ID (删除当前及子分类)

Think PHP递归获取所有的子分类的ID (删除当前及子分类)

SQL 递归查询,意淫CTE递归的执行步骤

PHP 根据子ID递归获取父级ID,实现逐级分类导航效果