最近项目中碰到需要写递归,就特意实现了集中实现方式,总结一下~
情景:通过给出的机构id,得到该机构id以及所有的子机构信息,机构id是UUID;
通过三种方式去实现,亲自实现过,可直接用:
第一种:通过多次操作数据库获得所有子机构信息。实现如下:
/**
* 递归获取某个机构id下面的所有子机构
* @param comTreeBeanHashSet 节点集合
* @param mechanismId 当前机构ID
*/
private void findChildMechanisms(Set<ComTreeBean> comTreeBeanHashSet, String mechanismId) {
ComTreeBean dep=comTreeDao.findByMechanismId(mechanismId);
List<ComTreeBean> comTreeBeans = new ArrayList<ComTreeBean>();
comTreeBeans.add(dep);
/**
* 加入当前机构
*/
comTreeBeanHashSet.addAll(comTreeBeans.stream().collect(Collectors.toList()));
/**
* 获取子机构
*/
List<ComTreeBean> comTreeBeanPars = comTreeDao.findByParentId(mechanismId);
for (ComTreeBean d : comTreeBeanPars) {
/**
* 递归子单位
*/
findChildMechanisms(comTreeBeanHashSet, d.getUid());
}
}
第二种:不会多次操作数据库,通过一次查询,获取所有机构树信息,再从当前机构去递归获取所有子机构信息
//子节点集合
List<ComTreeBean> childMenu = new ArrayList<ComTreeBean>;
/**
* 获取某个父节点下面的所有子节点
* @param menuList
* @param id 当前机构id
* @return
*/
public static List<ComTreeBean> treeMenuList(List<ComTreeBean> childMenu,
List<ComTreeBean> menuList, String id){
for(ComTreeBean mu: menuList){
//遍历出父id等于参数的id,add进子节点集合
if(id.equals(mu.getParComUid())){
//递归遍历下一级
treeMenuList(childMenu,menuList,mu.getUid());
childMenu.add(mu);
}
}
return childMenu;
}
直接使用能获取所有子机构信息,但是不能获取传入机构信息,如果想保留当前传入id机构,在初始化子节点集合时放入当前机构即可,即为:
//子节点集合
List<ComTreeBean> childMenu = comTreeBeanList.stream().filter(comTreeBean ->
pid.equals(comTreeBean.getUid())).collect(Collectors.toList());
当然,这两种方式都是机构树的数据不是很大,考虑到如果其他情况下,比如数据量大,就考虑使用第三种方式,通过创建存储过程实现,我也将其实现了一遍,表实例就不给出了,具体实现如下,可自己创建表实例实验:
第三种:存储过程
首先定义执行递归操作的存储过程,如下
-- 首先定义执行递归操作的存储过程:findChildList
CREATE PROCEDURE findChildList(IN id varchar(100))
BEGIN
DECLARE v_dep varchar(100) DEFAULT -1;
DECLARE done varchar(100) DEFAULT 0;
DECLARE C_dep CURSOR FOR SELECT d.id FROM T_COM_INFO d WHERE d.par_com_uid = id;
DECLARE CONTINUE HANDLER FOR NOT found set done=1;
SET @@max_sp_recursion_depth = 10;
INSERT INTO tmp_Dep VALUES (id);
OPEN C_dep;
FETCH C_dep INTO v_dep;
WHILE (done =0)
DO
CALL findChildList(v_dep);
FETCH C_dep INTO v_dep;
END WHILE;
END
然后定义调用递归操作的存储过程,如下
-- 再定义调用递归操作的存储过程:findDepList
CREATE PROCEDURE findDepList(IN id varchar(100))
BEGIN
DROP TEMPORARY TABLE IF EXISTS tmp_Dep;
CREATE TEMPORARY TABLE tmp_Dep(depId varchar(100));
DELETE FROM tmp_Dep;
CALL findChildList(id);
SELECT distinct tmp_Dep.depId,T_COM_INFO.com_name FROM tmp_Dep,T_COM_INFO where tmp_Dep.depId = T_COM_INFO.id order by depId;
END
调用存储过程及删除存储过程,如下:
call findDepList('45e9b12d-165f6037fad-9c1534b1e8dbb5a0c0ec3f70d24f9627')
drop procedure if exists findChildList
drop procedure if exists findDepList
具体就是这样,顺便给出本人写测试时,id为int类型的存储过程,如下
-- 首先定义执行递归操作的存储过程:findChildList
CREATE PROCEDURE findChildList(IN id BIGINT)
BEGIN
DECLARE v_dep integer DEFAULT -1;
DECLARE done integer DEFAULT 0;
DECLARE C_dep CURSOR FOR SELECT d.id FROM treenodes d WHERE d.pid = id;
DECLARE CONTINUE HANDLER FOR NOT found set done=1;
SET @@max_sp_recursion_depth = 10;
INSERT INTO tmp_Dep VALUES (id);
OPEN C_dep;
FETCH C_dep INTO v_dep;
WHILE (done =0)
DO
CALL findChildList(v_dep);
FETCH C_dep INTO v_dep;
END WHILE;
END
-- 再定义调用递归操作的存储过程:findDepList
CREATE PROCEDURE findDepList(IN id BIGINT)
BEGIN
DROP TEMPORARY TABLE IF EXISTS tmp_Dep;
CREATE TEMPORARY TABLE tmp_Dep(depId INTEGER);
DELETE FROM tmp_Dep;
CALL findChildList(id);
SELECT distinct tmp_Dep.depId,treenodes.nodename FROM tmp_Dep,treenodes where tmp_Dep.depId = treenodes.id order by depId;
END
drop procedure if exists findChildList
drop procedure if exists findDepList
call findDepList(3)