天天看点

mysql根据父节点递归查询所有子节点,List转树形结构工具类

经常有业务需要递归查询MySQL树形结构某一节点的所有子节点,每次从网上扒拉找都得找半天,索性就自己总结一些自己遇到的比较好用的一些方法。

SQL方法一:

SELECT
  * 
FROM
  (
  SELECT
    t1.*,
  IF
    ( FIND_IN_SET( parent_id, @parent_ids ) > 0, @parent_ids := CONCAT( @parent_ids, ',', id ), '0' ) AS ischild 
  FROM
    ( SELECT * FROM blade_menu AS t WHERE t.is_deleted = 0 AND client_type = 'dianduyun_app' ORDER BY t.id ASC ) t1,
    ( SELECT @parent_ids := '1508255373140103170' ) t2 
  ) t3 
WHERE
  ischild != '0'      

需要修改的地方

  • parent_id,改为你的父级id字段
  • blade_menu,改为你的表名称
  • WHEREt.is_deleted = 0,改为你的查询条件
  • @parent_ids := ‘1508255373140103170’,值改为你要传入的父级id

执行结果

mysql根据父节点递归查询所有子节点,List转树形结构工具类

SQL方法二:

SELECT
  rd.* 
FROM
  ( SELECT * FROM fine_authority_object WHERE parentId IS NOT NULL AND is_deleted = 0 ) rd,
  ( SELECT @pid := '2342465874553522423' ) pd 
WHERE
  FIND_IN_SET( parentId, @pid ) > 0 
  AND @pid := concat( @pid, ',', id ) 

UNION
SELECT
  * 
FROM
  fine_authority_object 
WHERE
  FIND_IN_SET( id, @pid ) > 0;      

需要修改的地方

  • fine_authority_object,改为你的表名,以及后面的查询条件进行修改。
  • SELECT @pid := ‘2342465874553522423’ ,值改为你要传的父id的值
  • FIND_IN_SET(parentId, @pid ) ,parentId改为你的父级id字段名

备注:

  • 当前这条SQL是根据多个父节点查询所有子节点(包含自身)
  • 如果不想查询结果包含自身,去掉后边的union

执行结果示例

mysql根据父节点递归查询所有子节点,List转树形结构工具类

Java List转树形结构

另外再分享一个将上面查询出来的list给转成树形结构的形式给前端返回的一个工具类。
public static List<ReportTemplateVo> listToTree2(List<ReportTemplateVo> list) {
        List<ReportTemplateVo> tree = new ArrayList<>();
        for (ReportTemplateVo ReportTemplateVo : list) {
            //找到根节点
            if (ReportTemplateVo.getParentId().equals("reportlets")) {
                tree.add(findChildren(ReportTemplateVo, list));
            }
        }
        return tree;
    }

    /**
     * 查找ReportTemplateVo的子节点
     * @param ReportTemplateVo
     * @param list
     * @return
     */
    private static ReportTemplateVo findChildren(ReportTemplateVo ReportTemplateVo, List<ReportTemplateVo> list) {
        List<ReportTemplateVo> children = new ArrayList<>();
        for (ReportTemplateVo node : list) {
            if (node.getParentId().equals(ReportTemplateVo.getId())) {
                //递归调用
                children.add(findChildren(node, list));
            }
        }
        ReportTemplateVo.setChildren(children);
        return ReportTemplateVo;
    }      

ReportTemplateVo实体:

public class ReportTemplateVo  {
    private static final long serialVersionUID = 1L;
    /**
     * 主键ID
     */
    private String id;

    /**
     * 父节点ID
     */
    private String parentId;

    /**
     * 子孙节点
     */
    private List<ReportTemplateVo> children;

    @ApiModelProperty("节点是否可以被选中")
    private Boolean disabled;

    /**
     * 节点名称
     */
    @ApiModelProperty("节点名称")
    private String title;
 
      

总结