1. 程式人生 > >儲存過程遞迴樹結構實現(某一節點下所有子節點)三種方式

儲存過程遞迴樹結構實現(某一節點下所有子節點)三種方式

最近專案中碰到需要寫遞迴,就特意實現了集中實現方式,總結一下~

情景:通過給出的機構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)