(记录贴)java后台实现树形菜单+分页返回数据

问题介绍

这几天做一个功能,也是第一次做树形菜单+分页的功能,觉得挺有意思,记录一下,可以大致看看原型图,要做成什么样子,如下图,要求能分页显示树形菜单。
在这里插入图片描述

一、实现思路v1

1.1 第一版

Controller层调用一个递归方法getChild(),传参数0进去,数据库中我parent_id设置为0表示最上级,相当于树的根节点,这里传一个0,就可以获取到树的所有结构。

List<RoadPatrolReportConfigVO> reportConfigResults = getChild(0L);//递归获取子节点,0表示顶级父类
public List<RoadPatrolReportConfigVO> getChild(Long pid){
        //递归时给子集创建List
        List<RoadPatrolReportConfigVO> reportConfigList = new ArrayList<>();
        //查出所有等于pid的节点的集合
        List<RoadPatrolReportConfigVO> reportConfigNodes = RoadPatrolReportConfigDbTool.getMapper().findParent(pid);

        if (reportConfigNodes!=null){
            /*遍历当前节点*/
            reportConfigNodes.forEach(x->{
                /*设置每个节点的子节点(调用自身再次查询子节点,将当前节点的ID作为父节点查询子节点)*/
                x.setChildren(getChild(x.getId()));
                /*将节点添加到集合中一并返回*/
                reportConfigList.add(x);
            });
        }
        return reportConfigList;
    }

这里mapper层有个方法,findParent方法

List<RoadPatrolReportConfigVO> findParent(@Param("pid") Long pid);
<select id="findParent" resultType="com.vkl.dao.vo.road.RoadPatrolReportConfigVO">
        select * from road_patrol_report_config rprc where parent_id = #{pid}
</select>

在这里插入图片描述

这样就可以获取到整个树形结构
在这里插入图片描述
然后用分页插件,PageHelper或者其它分页插件,依赖导入一下,就可以将最后得到的List转成Page,这个我是受到下面这篇博客的启发 Java树形菜单实现思路

注意:
但是不知道大家是否有想到这里其实存在一个问题,就是如果顶级父类的数量很多,比如有20个,但是你分页一般传pageNum=1,pageSize=10,这样的话,用上面这个版本,通过0作为顶级父类id,是可以查出来,但是会对所有的数据进行一个遍历,本来只要前10个顶级父类显示,这里却对后面不用显示的10个也进行了一次遍历,这其实可以进行优化一下,先查出pageSize个(假设10个)顶级父类,然后分别对这些父类进行遍历,这样在最开始就进行了分页,不用对所有顶级父类都进行遍历,显示多少就遍历递归多少。

但是话又说回来,如果你不需要做分页,只需要做成树形结构显示, 那你可以用上面的
在这里插入图片描述

1.2 第一版优化后

Controller层,主要看思路

{
Page page = new Page(pageNum, pageSize);
//下面queryPageforParent查找出所有顶级父类,即parent_id为0的
RoadPatrolReportConfigDbTool.getMapper().queryPageforParent(page,eventType,problemClasses);//eventType,problemClasses为两个条件,搜索有的
List<RoadPatrolReportConfigVO> voList = page.getRecords();
getChild(voList);//递归形成树结构
page.setRecords(voList);
return ResultMsg.success(page);
}
private List<RoadPatrolReportConfigVO> getChild(List<RoadPatrolReportConfigVO> list){
        //分别遍历每个顶级父类
        for (RoadPatrolReportConfigVO entry : list) {

            Long id = entry.getId();//顶级父类的id

            //父id=id,就表示是id的孩子,从而获取到id的所有孩子
            List<RoadPatrolReportConfigVO> childs = RoadPatrolReportConfigDbTool.getMapper().selectAllChildren(id);
            System.out.println(childs);
            //做一个判断,符合有孩子条件就进入继续递归,就像链表一样把路径上所有孩子遍历完再递归setChilds
            if (childs != null && childs.size() != 0) {
                getChild(childs);
                entry.setChildren(childs);
            }
        }
        return list;
}

queryPageforParent和selectAllChildren主要是mapper层写xml的sql语句
del_flag表示逻辑删除字段

下面是queryPageforParent

SELECT	rc.id,rc.report_code,rc.problem_classes,
		rc.problem_desc,
        rc.solve_method,
        rc.solve_limit,
        rc.sort,
        rc.parent_id,
        rc.emergency_id,
        e.event_type
        FROM
        road_patrol_report_config rc
        LEFT JOIN road_event_emergency e ON e.id = rc.emergency_id
        where rc.parent_id = 0 and rc.del_flag = '0'

下面是selectAllChildren,这个id就是RoadPatrolReportConfigDbTool.getMapper().selectAllChildren(id);传过来的id,也就是顶级父类的id

select temp.*,e.event_type
from (select * from road_patrol_report_config) temp
left join road_patrol_report_config rprc on temp.parent_id = rprc.id
left join road_event_emergency e on e.id=temp.emergency_id
where temp.del_flag='0' and temp.parent_id = #{id}

上面就是优化版,不会全部查找,page要多少查多少,避免浪费,大家的数据库肯定不一样,但是可以借鉴思路
在这里插入图片描述

二、实现思路v2

后来网络上看到另外一种实现方式,感觉更简单,这里记录一下,就是先找一级菜单,然后再递归填充子菜单即可

@Override
public List<Menu> getAllMenu() {
    // 一级菜单
    LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper();
    wrapper.eq(Menu::getParentId, 0);
    List<Menu> menuList = this.list(wrapper);
    // 子菜单
    setMenuChildren(menuList);
    return menuList;
}

private void setMenuChildren(List<Menu> menuList) {
    if(menuList != null) {
        for (Menu menu:menuList) {
            LambdaQueryWrapper<Menu> subWrapper = new LambdaQueryWrapper();
            subWrapper.eq(Menu::getParentId, menu.getMenuId());
            List<Menu> subMenuList = this.list(subWrapper);
            menu.setChildren(subMenuList);
            // 递归
            setMenuChildren(subMenuList);
        }
    }
}
  • 7
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小样x

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

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

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

打赏作者

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

抵扣说明:

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

余额充值