数据库查询层级结构

目的:我们要查一个菜单,菜单有个parent_id字段,可以绑定父级餐单,我们想让他展示层树的形态返回数据。即下图

{
    "menuId": 0,
    "menuName": "首页",
    "permissions": [
        {
            "menuId": 40,
            "menuName": "游戏管理",
            "parentId": 0,
            "isSelected": 1,
            "permissions": [
                {
                    "menuId": 41,
                    "menuName": "游戏基本信息",
                    "parentId": 40,
                    "isSelected": 1
                },
                {
                    "menuId": 42,
                    "menuName": "游戏客户端",
                    "parentId": 40,
                    "isSelected": 1
                },
                {
                    "menuId": 43,
                    "menuName": "游戏更新",
                    "parentId": 40,
                    "isSelected": 1
                },
                {
                    "menuId": 66,
                    "menuName": "游戏白名单列表",
                    "parentId": 40,
                    "isSelected": 1
                },
                {
                    "menuId": 79,
                    "menuName": "游戏数据",
                    "parentId": 40,
                    "isSelected": 1
                },
                {
                    "menuId": 83,
                    "menuName": "留存数据",
                    "parentId": 40,
                    "isSelected": 1
                },
                {
                    "menuId": 85,
                    "menuName": "测试白名单",
                    "parentId": 40,
                    "isSelected": 1
                },
                {
                    "menuId": 89,
                    "menuName": "双端互通",
                    "parentId": 40,
                    "isSelected": 1
                },
                {
                    "menuId": 115,
                    "menuName": "游戏公告",
                    "parentId": 40,
                    "isSelected": 1
                },
                {
                    "menuId": 120,
                    "menuName": "游戏Ltv",
                    "parentId": 40,
                    "isSelected": 1
                },
                {
                    "menuId": 129,
                    "menuName": "游戏Ltv",
                    "parentId": 40,
                    "isSelected": 1
                }
            ]
        },
        {
            "menuId": 44,
            "menuName": "用户管理",
            "parentId": 0,
            "isSelected": 1,
            "permissions": [
                {
                    "menuId": 45,
                    "menuName": "用户详情",
                    "parentId": 44,
                    "isSelected": 1
                },
                {
                    "menuId": 46,
                    "menuName": "用户日志",
                    "parentId": 44,
                    "isSelected": 1,
                    "permissions": [
                        {
                            "menuId": 48,
                            "menuName": "用户行为日志",
                            "parentId": 46,
                            "isSelected": 1
                        },
                        {
                            "menuId": 49,
                            "menuName": "用户设备日志",
                            "parentId": 46,
                            "isSelected": 1
                        }
                    ]
                }
            ]
        },
        {
            "menuId": 50,
            "menuName": "消费管理",
            "parentId": 0,
            "isSelected": 1,
            "permissions": [
                {
                    "menuId": 51,
                    "menuName": "订单管理",
                    "parentId": 50,
                    "isSelected": 1
                },
                {
                    "menuId": 64,
                    "menuName": "商品管理",
                    "parentId": 50,
                    "isSelected": 1
                }
            ]
        },
        {
            "menuId": 59,
            "menuName": "通用管理",
            "parentId": 0,
            "isSelected": 1,
            "permissions": [
                {
                    "menuId": 60,
                    "menuName": "全局配置",
                    "parentId": 59,
                    "isSelected": 1
                },
                {
                    "menuId": 61,
                    "menuName": "系统配置",
                    "parentId": 59,
                    "isSelected": 1
                },
                {
                    "menuId": 62,
                    "menuName": "权限管理",
                    "parentId": 59,
                    "isSelected": 1
                },
                {
                    "menuId": 122,
                    "menuName": "角色管理",
                    "parentId": 59,
                    "isSelected": 1
                }
            ]
        },
        {
            "menuId": 97,
            "menuName": "官网管理",
            "parentId": 0,
            "isSelected": 1,
            "permissions": [
                {
                    "menuId": 98,
                    "menuName": "官网游戏管理",
                    "parentId": 97,
                    "isSelected": 1
                },
                {
                    "menuId": 99,
                    "menuName": "礼包管理",
                    "parentId": 97,
                    "isSelected": 1
                }
            ]
        }
    ]
}

解决方法:

1.数据库查询出的结果就具有层级结构,通过写数据库语句实现

SQL 层级查询(一) - 腾讯云开发者社区-腾讯云 (tencent.com)

2.我们将查询出来的数据进行改装,通过java代码的形式,使其变成层级结构

第一步,数据库语句查询

可以看到,我们的菜单都有个父级菜单字段,我们除了查询餐单id,菜单名称,还要把父级id查询出来

第二步,写个DTO类,用于存数据,DTO类需要有个List<自己>的字段

 第三步,编写数据转为树形结构Java代码

    /**
     * 将数据库中的菜单转换为树形结构
     *
     * @param permissionDOs 系统菜单
     * @return 树形结构
     *
     */
    public static PermissionDTO getMenuTreeByRole(List<PermissionDTO> permissionDOs) {
        Map<Integer, List<PermissionDTO>> systemMenuMap = permissionDOs.stream()
                .collect(Collectors.groupingBy(PermissionDTO::getParentId));
        PermissionDTO permissionDTO = new PermissionDTO();
        permissionDTO.setMenuId(0);
        permissionDTO.setMenuName("首页");
        listToTreeByRole(systemMenuMap, permissionDTO);
        return permissionDTO;
    }

    /**
     * 将列表转换为树形结构
     *
     * @param collect       列表
     * @param  permissionDTO 角色权限
     */
    private static void listToTreeByRole(Map<Integer, List<PermissionDTO>> collect, PermissionDTO permissionDTO) {
        List<PermissionDTO> treeMenuNodes = collect.get(permissionDTO.getMenuId());
        if (!CollectionUtils.isEmpty(treeMenuNodes)) {
            List<PermissionDTO> permissions = new ArrayList<>();
            BeanCopyUtil.copyColl(treeMenuNodes, permissions, PermissionDTO.class);
            permissionDTO.setPermissions(permissions);
            permissionDTO.getPermissions().forEach(t -> listToTreeByRole(collect, t));
        }
    }

方法解读:

1.首先,我们将得到的数据库数据通过parent_id进行分组,即map结构,key为parent_id,value为组成员

 2.设置第一级菜单,即没有父级菜单id为0的,调用递归方法listToTreeByRole,设置他的自己菜单

3.递归方法第一步,即通过当前菜单id,从我们的map中获取其子菜单(前面我们的map分过组了,所以我们可以很容易的得到当前key下的子菜单)

 4.子菜单不为空,就把子菜单绑定到当前菜单对象的下面

5.递归,对子菜单执行操作

6.结果

得到一个PermissionDTO对象 

递归结构:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晚霞虽美不如你

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值