在MySQL中自定义函数来实现递归获取所有子节点,该方式的优点是可以减少java代码量,缺点是:1.不好维护;2.拼接的字段太长的时候,自定义函数的返回值可能容量不够,此时可以定义为text等大容量类型;3:show variables like 'group_concat_max_len' 查看group_concat的容量为1024 ,具体内容查看:https://blog.csdn.net/world_ding/article/details/54286862
。还有一个注意点,在生产环境中要给自定义的函数分配权限,不然可能会没有权限请求这个自定义的函数。
1.MySQL表结构和数据
/*
Navicat MySQL Data Transfer
Source Server : localhost_3306
Source Server Version : 50712
Source Host : localhost:3306
Source Database : test
Target Server Type : MYSQL
Target Server Version : 50712
File Encoding : 65001
Date: 2018-04-13 12:47:42
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for treenodes
-- ----------------------------
DROP TABLE IF EXISTS `treenodes`;
CREATE TABLE `treenodes` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`nodename` varchar(50) DEFAULT NULL,
`pid` int(11) DEFAULT '0',
`text` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of treenodes
-- ----------------------------
INSERT INTO `treenodes` VALUES ('1', 'A', '0', null);
INSERT INTO `treenodes` VALUES ('2', 'B', '1', null);
INSERT INTO `treenodes` VALUES ('3', 'C', '1', null);
INSERT INTO `treenodes` VALUES ('4', 'D', '2', null);
INSERT INTO `treenodes` VALUES ('5', 'E', '2', null);
INSERT INTO `treenodes` VALUES ('6', 'F', '3', null);
INSERT INTO `treenodes` VALUES ('7', 'G', '6', null);
INSERT INTO `treenodes` VALUES ('8', 'H', '0', null);
INSERT INTO `treenodes` VALUES ('9', 'I', '8', null);
INSERT INTO `treenodes` VALUES ('10', 'J', '8', null);
INSERT INTO `treenodes` VALUES ('11', 'K', '8', null);
INSERT INTO `treenodes` VALUES ('12', 'L', '9', null);
INSERT INTO `treenodes` VALUES ('13', 'M', '9', null);
INSERT INTO `treenodes` VALUES ('14', 'N', '12', null);
INSERT INTO `treenodes` VALUES ('15', 'O', '12', null);
INSERT INTO `treenodes` VALUES ('16', 'P', '15', null);
INSERT INTO `treenodes` VALUES ('17', 'Q', '15', null);
INSERT INTO `treenodes` VALUES ('18', '一级机构', '7', null);
INSERT INTO `treenodes` VALUES ('19', '二级机构', '18', null);
INSERT INTO `treenodes` VALUES ('20', '三级机构', '19', null);
INSERT INTO `treenodes` VALUES ('21', '销售经理', '20', null);
INSERT INTO `treenodes` VALUES ('22', '销售经理2', '21', null);
INSERT INTO `treenodes` VALUES ('23', '代理人', '22', null);
INSERT INTO `treenodes` VALUES ('24', '代理人', '22', null);
INSERT INTO `treenodes` VALUES ('25', '不该出现', null, null);
2.自定义获取某个父节点下面的所有子节点的函数
CREATE FUNCTION `getChildList`(rootId INT)
RETURNS varchar(1000)
BEGIN
#声明两个局部变量
DECLARE sTemp VARCHAR(1000);
DECLARE sTempChd VARCHAR(1000);
#初始化局部变量
SET sTemp = '$';
#调用cast函数将int转换为char
SET sTempChd =cast(rootId as CHAR);
#递归拼接
WHILE sTempChd is not null DO
#存储每次递归结果
SET sTemp = concat(sTemp,',',sTempChd);
#将参数作为pid,然后查询其子id,然后将子id作为pid,
#查询以子id为pid的子id,依次循环下去,直到所有节点都为叶子节点
SELECT group_concat(id) INTO sTempChd FROM treeNodes where FIND_IN_SET(pid,sTempChd)>0;
END WHILE;
RETURN sTemp;
END
#测试
select * from treenodes where FIND_IN_SET(id,getChildList(20));
3.自定义获取子节点上的所有父节点函数
CREATE FUNCTION `getParList`(rootId INT)
RETURNS varchar(1000)
BEGIN
DECLARE sTemp VARCHAR(1000);
DECLARE sTempPar VARCHAR(1000);
SET sTemp = '';
SET sTempPar =rootId;
#循环递归
WHILE sTempPar is not null DO
#判断是否是第一个,不加的话第一个会为空
IF sTemp != '' THEN
SET sTemp = concat(sTemp,',',sTempPar);
ELSE
SET sTemp = sTempPar;
END IF;
SET sTemp = concat(sTemp,',',sTempPar);
SELECT group_concat(pid) INTO sTempPar FROM treenodes where pid<>id and FIND_IN_SET(id,sTempPar)>0;
END WHILE;
RETURN sTemp;
END
#测试
select * from treenodes where FIND_IN_SET(id,getParList(15));
4.删除自定义的函数
DROP FUNCTION `getChildList`;