一、数据库父子结构数据设计

    大部分采用 parentId的形式来存储父id,并且只存储父id,祖父Id不存储。也可以添加存储层级级别或者层级关系等字段。

CREATE TABLE `t_resource` (
  `id` varchar(255) NOT NULL COMMENT '主键',
  `parent_id` varchar(255) DEFAULT NULL COMMENT '父ID',
  `name` varchar(255) DEFAULT NULL COMMENT '名称',
  `url` varchar(255) DEFAULT NULL COMMENT '资源url',
  `level` varchar(255) DEFAULT NULL COMMENT '层级级别',
  `decode` varchar(255) DEFAULT NULL COMMENT '层级ID的关系,用”_“分割',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

  

 

二、将有父子关系的数据转换成树形结构数据

   mapper层获取数据库数据和 controller层处理很简单,将有父子关系的数据转换成树形结构数据交给 service层处理。

    @PostMapping("/getMuneTree")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> getMuneTree(){
        Map<String, Object> map = new HashMap<>();
        map.put("menuList", resourceDOService.getMuneTree());
        return ResponseEntity.ok(map);
    }

      

    1、方式一:递归:从树的最顶级获取子级,然后子级获取其子级。

          返回时,需要哪些字段值就添加哪些字段值到 map中。结果图如上

    /**
     * 将有父子关系的数据转换成树形结构数据
     *
     * @return 最终的树状结构的集合数据
     */
    @Override
    public List<Map<String, Object>> getMuneTree() {
        // 获取数据库中带有有父子关系的数据
        List<ResourceDO> data = resourceDOMapper.selectAll();
        
        //创建一个List集合来存放最终的树状结构数据
        List<Map<String, Object>> menuList = new ArrayList<>();
        // 先存入最顶级的树(0代表没有父级,即最顶级),然后通过最顶级的id递归获取子级
        for (ResourceDO entity : data) {
            Map<String, Object> map = new HashMap<>();
            if ("0".equals(entity.getParentId())) {
                map.put("id", entity.getId());
                map.put("parentId", entity.getParentId());
                map.put("name", entity.getName());
                map.put("children", getChildren(data, entity.getId()));
                menuList.add(map);
            }
        }
        return menuList;
    }

    /**
     * 递归处理:通过id获取子级,查询子级下的子级
     *
     * @param data 数据库的原始数据
     * @param id   主id
     * @return  该id下得子级
     */
    public List<Map<String, Object>> getChildren(List<ResourceDO> data, String id) {
        List<Map<String, Object>> list = new ArrayList<>();
        if (data == null || data.size() == 0 || id == null) {
            return list;
        }
        for (ResourceDO entity : data) {
            Map<String, Object> map = new HashMap<>();
            //如果本级id与数据的父id相同,就说明是子父级关系
            if (id.equals(entity.getParentId())) {
                map.put("id", entity.getId());
                map.put("parentId", entity.getParentId());
                map.put("name", entity.getName());
                //查询子级下的子级
                map.put("children", getChildren(data, entity.getId()));
                list.add(map);
            }
        }
        return list;
    }

    2、方式二:组装带有children关联性的对象

        在实体列中定义一个 children集合:

    private List<ResourceDO> children = new ArrayList<>();

       返回的是实体类对象的所有值,这里操作的都是集合存储对象的引用

    /**
     * 将有父子关系的数据转换成树形结构数据
     *
     * @return 最终的树状结构的集合数据
     */
    @Override
    public List<ResourceDO> getMuneTree2() {
        // 获取数据库中带有有父子关系的数据
        List<ResourceDO> data = resourceDOMapper.selectAll();

        // 复制data数据
        List<ResourceDO> menuList = new ArrayList<>(data);
        // 遍历两次data来组装带有children关联性的对象,如果找到子级就删除menuList的数据
        for (ResourceDO entity : data) {
            for (ResourceDO entity2 : data) {
                //如果本级id与数据的父id相同,就说明是子父级关系
                if (entity.getId().equals(entity2.getParentId())) {
                    entity.getChildren().add(entity2);
                    menuList.remove(entity2);
                }
            }
        }
        return menuList;
    }

 

 

ends~

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐