递归查询一张表里树形结构的数据

484 阅读2分钟

我正在参加「掘金·启航计划」

返回树形结构数据

通过Java语言操作

如果我们想要返回树形结构的数据形式,类似于评论这种,那通过Java操作其实就是:

  1. 首先查到所要的完整数据
  2. 由于树形数据一定是有父节点的编号的,所以肯定写成递归
  3. 可以通过stream来优美的表示

上代码(这里使用了mybatis-plus):

//递归查找所有菜单的子菜单
private List<CategoryEntity> getChildrens(CategoryEntity root, List<CategoryEntity> all) {
​
    List<CategoryEntity> children = all.stream().filter(categoryEntity -> {
        return categoryEntity.getParentCid() == root.getCatId();
    }).map(categoryEntity -> {
        //1、找到子菜单
        categoryEntity.setChildren(getChildrens(categoryEntity, all));
        return categoryEntity;
    }).sorted((menu1, menu2) -> {
        //2、菜单的排序
        return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
    }).collect(Collectors.toList());
​
    return children;
}
​
public List<CategoryEntity> listWithTree() {
    //1、查出所有分类
    List<CategoryEntity> entities = baseMapper.selectList(null);
​
    //2、组装成父子的树形结构
​
    // 找到所有的一级分类
    List<CategoryEntity> level1Menus = entities.stream().filter(categoryEntity ->
                                                                categoryEntity.getParentCid() == 0
                                                               ).map((menu) -> {
        menu.setChildren(getChildrens(menu, entities));
        return menu;
    }).sorted((menu1, menu2) -> {
        return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
    }).collect(Collectors.toList());
​
​
    return level1Menus;
}

listWithTree就是我们的方法,递归调用了getChildrens来查找,而setChildren就是一个setter方法

通过Mybatis操作

先创建一个数据表

create table tree
(
    id        bigint       not null
        primary key,
    parent_id bigint       not null,
    sort      int          not null,
    name      varchar(100) not null
);

一些数据

INSERT INTO MY_TABLE(id, first_name, last_name, birth) VALUES (10001, 'Georgi', 'Facello', 'M');
INSERT INTO MY_TABLE(id, first_name, last_name, birth) VALUES (10002, 'Bezalel', 'Simmel', 'F');
INSERT INTO MY_TABLE(id, first_name, last_name, birth) VALUES (10003, 'Parto', 'Bamford', 'M');
INSERT INTO MY_TABLE(id, first_name, last_name, birth) VALUES (10004, 'Chirstian', 'Koblick', 'M');
INSERT INTO MY_TABLE(id, first_name, last_name, birth) VALUES (10005, 'Kyoichi', 'Maliniak', 'M');
INSERT INTO MY_TABLE(id, first_name, last_name, birth) VALUES (10006, 'Anneke', 'Preusig', 'F');
INSERT INTO MY_TABLE(id, first_name, last_name, birth) VALUES (10007, 'Tzvetan', 'Zielinski', 'F');
INSERT INTO MY_TABLE(id, first_name, last_name, birth) VALUES (10008, 'Saniya', 'Kalloufi', 'M');
INSERT INTO MY_TABLE(id, first_name, last_name, birth) VALUES (10009, 'Sumant', 'Peac', 'F');
INSERT INTO MY_TABLE(id, first_name, last_name, birth) VALUES (10010, 'Duangkaew', 'Piveteau', 'F');

对应的bean

@Getter
@Setter
@ToString
public class Tree {
​
    private Long id;
    private Long parentId;
    private Integer sort;
    private String name;
​
    private List<Tree> children;
​
}

这里面关键词都很好懂,sort就是排序字段,children就是子数据

来个Mapper

@Mapper
public interface TreeMapper {
​
    List<Tree> getAllSort();
​
}

对应的xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.he.dao.TreeMapper">
    <resultMap id="resultMap" type="com.he.pojo.Tree">
        <id column="id" property="id"/>
        <result column="parent_id" property="parentId"/>
        <result column="sort" property="sort"/>
        <result column="name" property="name"/>
        <!--使用mybatis  collection 进行集合查询-->
        <collection property="children" ofType="com.he.pojo.Tree" select="selectTree" column="id"
                    javaType="java.util.ArrayList"/>
    </resultMap>
​
​
    <!--父级查询-->
    <select id="getAllSort" resultMap="resultMap">
        <!--从parent_id为0开始递归-->
        select * from tree where parent_id = 0 order by sort asc
    </select>
​
    <!--关联集合查询-->
    <select id="selectTree" parameterType="String" resultMap="resultMap">
        select *
        from tree
        where tree.parent_id = #{id}
        order by sort asc
    </select>
</mapper>

使用collection进行操作,里面嵌套了select的sql就可以了

这里面还有通过两个字段来定位1对多的情况,其实就是在collection的column中换成column="{id=id,grade=grade}"这样就可以一次性传2个参数。