部门组织树的通用数据库设计及代码的树形构造

在我们学习工作当中,树的这种结构已经屡见不鲜了,用的场景也很多
比如今天我为大家带来的就是工作中经常可能遇到的组织部门树 权限树 菜单树的构造
直接上张部门组织树的数据库设计吧
这里写图片描述

组织部门表
id 主键
name 名称
pid 父id
level 层级
seq 在当前层级下的顺序
remark 备注
这些是通用的字段 pid level(我没用上哈)seq 这些是这类问题的通解 的关键字段
在代码中 我们将依靠这些字段来递归进行树的构造 最后再按特定格式返给前端

下满上核心代码:

  private Comparator<SysDeptModel> comparator = new Comparator<SysDeptModel>() {
        @Override
        public int compare(SysDeptModel s1, SysDeptModel s2) {
            return s2.getSeq() - s1.getSeq();
        }
    };

    @GetMapping("/tree.json")
    public ResponseEnvelope toTree() {
        //查询所有的组织结构
        List<SysDeptModel> treeModels = sysDeptService.selectPage(new SysDeptModel(), null);
        Iterator<SysDeptModel> iterator = treeModels.iterator();
        //找出顶级组织机构(这里我们定义 顶级的pid为0 )
        ArrayList<SysDeptModel> rootNodes = Lists.newArrayList();
        while (iterator.hasNext()) {
            SysDeptModel node = iterator.next();
            if (node.getParentId() == 0) {
                rootNodes.add(node);
                iterator.remove();
            }
        }
        //为当前的组织机构排序(根据seq值)
        if (!rootNodes.isEmpty()) {
            rootNodes.sort(comparator);
        }
        //每隔从顶级开始递归寻找他们的子节点
        if (!treeModels.isEmpty() && !rootNodes.isEmpty()) {
            rootNodes.forEach(rootNode -> constructTree(rootNode, treeModels));
        }
        //返回结果
        return ResponseEnvelopFactory.success(rootNodes);
    }

    /**
     * 构造树
     *
     * @param parentNode 父节点
     * @param treeModels 剩余节点
     */
    private void constructTree(SysDeptModel parentNode, List<SysDeptModel> treeModels) {
        Iterator<SysDeptModel> iterator = treeModels.iterator();
        //保存子节点
        List<SysDeptModel> childrens = new ArrayList<>();

        while (iterator.hasNext()) {
            SysDeptModel node = iterator.next();
            //找出下一级的节点
            if (parentNode.getId().equals(node.getParentId())) {
                childrens.add(node);
                iterator.remove();
            }
        }
        //为当前节点排序
        if (!childrens.isEmpty()) {
            childrens.sort(comparator);
        }
        //设置当前子节点为当前父节点的子集
        if (!CollectionUtils.isEmpty(childrens)) {
            parentNode.setChild(childrens);
        }
        //递归进行上述步骤  当我们的子节点没有时就一个顶级组织的递归就结束了
        //当treeModels 空时 我们所有的顶级节点都把递归执行完了 就结束了
        if (!CollectionUtils.isEmpty(treeModels) && !childrens.isEmpty()) {
            childrens.forEach(node -> constructTree(node, treeModels));
        }
    }

看看我们的结果吧最后:

{
data: [
{
id: 2,
name: "总公司2",
seq: 1,
remark: "",
parentId: 0,
level: "0",
operator: "",
operteTime: 1536847342000,
operateIp: "",
child: [
{
id: 5,
name: "科技分公司",
seq: 1,
remark: "",
parentId: 2,
level: "1",
operator: "",
operteTime: 1536847351000,
operateIp: "",
child: [
{
id: 6,
name: "反特赛科技",
seq: 5,
remark: "",
parentId: 5,
level: "3",
operator: "",
operteTime: 1536847355000,
operateIp: "",
child: null
}
]
}
]
},
{
id: 1,
name: "总公司1",
seq: 0,
remark: "",
parentId: 0,
level: "0",
operator: "",
operteTime: 1536847338000,
operateIp: "",
child: [
{
id: 7,
name: "上海分公司",
seq: 5,
remark: "",
parentId: 1,
level: "2",
operator: "",
operteTime: 1536847473000,
operateIp: "",
child: null
},
{
id: 4,
name: "北京分公司",
seq: 3,
remark: "",
parentId: 1,
level: "1",
operator: "",
operteTime: 1538316148000,
operateIp: "",
child: null
},
{
id: 3,
name: "成都分公司",
seq: 2,
remark: "",
parentId: 1,
level: "1",
operator: "",
operteTime: 1536847345000,
operateIp: "",
child: null
}
]
}
],
status: true
}

结果是完全正确的哈 也有排序在的。
这就是这类问题的通用方法啦。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值