大家在做项目的时候,展示树形结构的数据,肯定遇到需要通过父节点递归查询所有子节点的情况,
也应该做过通过子节点查询所有父级节点的需求。
本次遇到的需求是一次性查询多个子节点的所有父级节点的情况。
多个节点我们考虑到要去除重复节点。
常规做法:
1. 数据库中写一个自定义函数,查询当前节点的所有父级节点
DROP FUNCTION if EXISTS fn_getParentNodes; CREATE FUNCTION fn_getParentNodes(currentId VARCHAR(64)) RETURNS VARCHAR(1000) BEGIN DECLARE parentId VARCHAR(100); DECLARE tempStr VARCHAR(1000) DEFAULT currentId; WHILE currentId is not null DO SET parentId = (SELECT pid FROM dept WHERE id = currentId ); IF parentId is not null THEN set tempStr = CONCAT(parentId,',',tempStr); set currentId = parentId; ELSE set currentId = parentId; END IF; END WHILE; RETURN tempStr; END;
SELECT id,pid,name from dept where FIND_IN_SET(id, fn_getParentNodes('11'))
2. 后台多次传递子节点调用当前子节点子查询所有父级节点。
3.单次调用到的结果存到List中。
4.多次调用的结果汇总,去重作为最终结果。
其实还有种最简单的做法:利用union查询,结果自动去重
SELECT id,pid,name from dept where FIND_IN_SET(id, fn_getParentNodes('11')) UNION SELECT id,pid,name from dept where FIND_IN_SET(id, fn_getParentNodes('18')) ORDER BY pid
如果达到如上效果,一种在mysql执行动态sql,
还有一种是通过mybatis foreach标签实现:
Mapper中的方法
/** * 查询多个部门的所有父级部门(递归,数据量大,肯定影响性能) * @param deptIds * @return */ List<ZTreeNode> getParentZTeeNodeByDeptIds(@Param("deptIds") String[] deptIds);
Mapper.xml 配置
<select id="getParentZTreeNodeByDeptIds" resultType="com.core.node.ZTreeNode"> <foreach collection="deptIds" index="index" item="i" separator="UNION" > SELECT id,pid,name FROM dept WHERE FIND_IN_SET(id, fn_getParentNodes(#{i})) </foreach> ORDER BY pid; </select>
这样能通过一次传递多个子节点参数 deptIds = 11,18,完成最终结果查询。