Java MySQL递归子级父级,构建树结构
Posted 符华-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java MySQL递归子级父级,构建树结构相关的知识,希望对你有一定的参考价值。
记录一下
目录
🥩 mysql递归子级、父级
🌭 递归所有子级
🥓 方式一:
注意:此方式只适用 id、parent_id 是数字或纯数字的字符串,否则不生效。
SELECT id,`name`
FROM (SELECT id,parent_id,`name` FROM sys_dept where parent_id != '0') a,
(SELECT @pv :=#parentId) b
WHERE (FIND_IN_SET(parent_id,@pv) != '0' AND @pv := concat(@pv, ',', id))
🥓 方式二:
注意:这个方法纯数字没问题,但是其他字符串不知道为什么有的时候可以,有的时候又不能获取到全部子级
之前一开始我验证这个方法的时候,id是64位随机字符串,parentId也一样,验证的时候是没问题的;但是后面我为了写这篇文章我改了部门表的数据,id、parentId同样是随机字符串,就突然不行了。比如获取某个公司下面所有分公司、单位部门,总共有四级,其中一个分公司下的一个部门没有获取到,自然这个部门的子级也没获取到。但是当我 #parentId 传那个分公司的id时又能获取到这个部门和它的子级。这个部门是3级的,它的子级是4级,可是这个公司还有其他的3级4级啊,其他的都能获取到,就它不行,不知道是为啥。
SELECT id,`name`
FROM(
SELECT id,`name`,IF(find_in_set(parent_id, @pv) != 'ROOT',@pv := concat(@pv, ',', id),'ROOT') AS childList
FROM (SELECT id,parent_id,`name` FROM sys_dept) a, (SELECT @pv :=#parentId) b
) t3
WHERE childList != 'ROOT';
🥓 方式三:
这下是真的改良版了,经过多次数据更改测试,无论是纯数字还是随机字符串,都没问题
这里包括了本身
SELECT b.id,b.parent_id,b.name
FROM(
SELECT @ids AS _ids,
(SELECT @ids := GROUP_CONCAT(id) FROM sys_dept WHERE FIND_IN_SET(parent_id, @ids)) AS cids
FROM sys_dept,(SELECT @ids := #parentId) b
WHERE @ids IS NOT NULL
) a,sys_dept b
WHERE FIND_IN_SET(b.id, a._ids)
ORDER BY LEVEL,id
效果:
🍔 递归所有父级
🍗 方式一:
我们可以直接从上面递归子级的方式三中,拿这个sql进行更改,经测试也是没问题的。这个也同样包括了它本身。
SELECT b.id,b.parent_id,b.name
FROM(
SELECT @ids AS _ids,
(SELECT @ids := GROUP_CONCAT(parent_id) FROM sys_dept WHERE FIND_IN_SET(id, @ids)) AS cids
FROM sys_dept,(SELECT @ids := #id) b
WHERE @ids IS NOT NULL
) a,sys_dept b
WHERE FIND_IN_SET(b.id, a._ids)
ORDER BY LEVEL,id
效果:
🥩 Java递归子级、父级
🍚 递归子级列表
/**
* 递归查询,获取子级列表(不包含本身)
*/
public List<SysDept> childIdList(String parentId)
List<SysDept> resultList = new ArrayList<>();
QueryWrapper<SysDept> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("parent_id",parentId);
queryWrapper.select("id");
List<SysDept> list = baseMapper.selectList(queryWrapper);
for (SysDept dept : list)
resultList.addAll(childIdList(dept.getId()));
list.addAll(resultList);
return list;
🍜 递归父级列表
/**
* 递归查询,获取父级列表(包含本身)
*/
public List<SysDept> parentIdList(String id)
List<SysDept> resultList = new ArrayList<>();
QueryWrapper<SysDept> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("id",id);
queryWrapper.select("parent_id","name");
List<SysDept> list = baseMapper.selectList(queryWrapper);
for (SysDept dept : list)
resultList.addAll(parentIdList(dept.getParentId()));
list.addAll(resultList);
return list;
🥩 TreeUtil 树结构构建工具
import cn.hutool.core.util.ReflectUtil;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* 树结构构建工具类
*/
public class TreeUtil
/**
* 根据反射获取属性值
* @param t 实体对象
* @param fieldName 属性名称
*/
private static<T> Object getFieldValue(T t,String fieldName)
Field field = ReflectUtil.getField(t.getClass(), fieldName);
return ReflectUtil.getFieldValue(t, field);
/**
* 获取树结构(知道顶级节点的id的情况下用)
* 比如部门列表,如果是管理员,那肯定是全部的数据,一般情况下,顶级节点的父级id都是0或ROOT,表示它是最顶级。
* 管理员获得全部数据,这种情况下就知道顶级节点的id的值,所以parentId直接传0或ROOT。
*/
public static<T> List<T> buildTreeIsRoot(List<T> list,String parentId)
List<T> root = buildTree(list, parentId);
getChild(root, list);
return root;
/**
* 获取树结构(parentId值不确定)
* 除了顶级节点可以确定parentId的值,其他的都是不确定的。
* 比如是部门经理,就只能看到自己部门和子部门的数据,构建的树结构也应该是只显示出本部门、子部门。
*/
public static<T> List<T> buildTreeNotRoot(List<T> list)
List<T> sources = new ArrayList<>(list);
List<T> result = new ArrayList<>();
for (T t : sources)
String parentId = (String)getFieldValue(t,"parentId");
List<T> root = buildTree(list, parentId);
getChild(root, list);
result.addAll(root);
return result;
/**
* 获取树结构
* @param list 数据
* @param pId 父级id
*/
private static<T> List<T> buildTree(List<T> list,String pId)
List<T> root= new ArrayList<>();
Iterator<T> it = list.iterator();
while (it.hasNext())
T t = it.next();
String parentId = (String)getFieldValue(t,"parentId");
if (parentId.equals(pId))
root.add(t);
it.remove();
return root;
/**
* 递归子节点
*/
public static<T> void getChild(List<T> root,List<T> list)
try
for (T nav : root)
String id = (String)getFieldValue(nav,"id");
List<T> childList = buildTree(list, id);
getChild(childList, list);
Field child = ReflectUtil.getField(nav.getClass(), "children");
child.set(nav,childList);
catch (Exception e)
e.printStackTrace();
以上是关于Java MySQL递归子级父级,构建树结构的主要内容,如果未能解决你的问题,请参考以下文章