阿里云开发者社区

电脑版
提示:原网页已由神马搜索转码, 内容由developer.aliyun.com提供.

【java】树形结构分页(真分页)

2024-04-25265
版权
版权声明:
本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《 阿里云开发者社区用户服务协议》和 《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写 侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介:【java】树形结构分页(真分页)

对于一个查询来说,如果数据量是不断增加的,并且对于最高权限要显示全表数据,就必须考虑真分页了,那么树形结构如何真分页呢?网上找了好多,并没有一个具体的方案,只能自己想一个了真分页: 即每次只从数据库取到相应的数据,然后返回,这样可以性能要比假分页高一些

假分页: 即查询数据库中符合条件的所有数据,然后在模型层,自己对list结果进行处理为相应的分页效果,或者由web进行分页展示

关联文章树形结构

需求

  • 按照最顶级节点数分页,不是所有数据条数
  • 返回一个树形结构
  • 根据权限进行数据结构筛选

优化方案

  • 前情回顾

之前使用了先查出项目的全表,然后在代码中新建list存储后进行筛选,筛选完利用全表数据进行组树,这样如果只有几千条数据,整体速度是在1s以下,还是可以接受,但是如果数据量一旦到10w、100w 就会造成严重的卡顿。

当时考虑真分页的困难在于,在筛选的情况下,如何保证最后返回到前端的条数是一致的,因为在筛选后分页的数据还要进行组树,这样无法保证条数一致,后来考虑过补树,不过过于麻烦,就放弃了。

  • 格局打开

既然单独的返回条数由于组树导致无法固定,换个角度,从前端来看,每次前端都是要首先显示一级项目,那么是不是可以先把符合筛选条件的一级项目查出来,然后再查询出每个树,然后再进行组树呢?

由于表结构是使用(id,pid)的方式来存储树形结构,所以要想实现树形结构真分页需要再增加一个字段firstNode(顶级节点),因为所谓分页就是将最后返回去的数据分批返回,所以就必须确定分页前的数据量是固定的

SELECT distinct    firstNodeFROM    Project p where p.name='龙腾集团项目'

上述sql就可以查出所有要返回前端的所有树形项目的一级项目id,并且是不重复的,所以每次分页都能保证返回的条数是固定的。

接下来 对PageResult firstNodeList

进行再次查询

 <if test="idList != null">                AND firstNode in                <foreach close=")" collection="idList" index="" item="item" open="(" separator=",">                    #{item}                </foreach> </if>

上述sql可以查出所有要返回前端的完整的树的项目,但是,其实是查多了,因为从一级项目查出所有的项目,就会将之前过滤的子项目又全部补全,实际上只筛选了一级项目,那么就要对项目进行再次筛选,因为我们项目后续有一些计算,所以把所有数据都查出来之后计算后使用的java筛选,没有必要就可以直接在上述sql直接筛选即可。

 public List<Project> getSortProjectList(List<Project> projectList, ProjectVo query) {        List<Project> projects = projectList.stream()                .filter(e -> query.getId() == null || isContaint(e.getId(), query.getId()))                .filter(e -> query.getProjectName() == null || isContaint(e.getProjectName(), query.getProjectName()))                .filter(e -> query.getProjectStatus() == null || query.getProjectStatus().equals(e.getProjectStatus()))                .filter(e -> query.getBusinessId() == null || query.getBusinessId().equals(e.getBusinessId()))                .filter(e -> query.getProjectType() == null || isContaint(e.getProjectType(), query.getProjectType()))                .filter(e -> query.getBusinessName() == null || isContaint(e.getBusinessName(), query.getBusinessName()))                .filter(e -> query.getCustomer() == null || query.getCustomer().equals(e.getCustomer()))                .filter(e -> query.getCreateUser() == null || query.getCreateUser().equals(e.getCreateUser()))                .filter(e -> query.getProjectManager() == null || query.getProjectManager().equals(e.getProjectManager()))                .filter(e -> query.getPriceId() == null || query.getPriceId().equals(e.getPriceId()))                .filter(e -> query.getPriceFlag() == null || isContaint(query.getPriceFlag(), e.getPriceFlag()))                .collect(Collectors.toList());        return projects;    }

筛选结束后,进行组树

 /**     * 从一级向下递归     *     * @param projectFatherList     * @return     */    public List<Project> getProjectTree(List<Project> projectFatherList, HashMap<String, List<Project>> allProjectMap) {        //遍历,拿出所有的pidw为零的项目        List<Project> firstLeaveProject = projectFatherList.stream().filter(project -> StringUtils.isEmpty(project.getPId())).collect(Collectors.toList());        projectFatherList = getAllBottomProject(firstLeaveProject, allProjectMap);        return projectFatherList;    }
/**     * 递归遍历此项目下所有项目     *     * @param leaveProjectList     * @return     */    public List<Project> getAllBottomProject(List<Project> leaveProjectList, HashMap<String, List<Project>> allProjectMap) {        if (leaveProjectList != null && leaveProjectList.size() != 0 && !allProjectMap.isEmpty()) {            for (int i = leaveProjectList.size() - 1; i >= 0; i--) {                if (leaveProjectList.get(i).getId() != null && allProjectMap.get(leaveProjectList.get(i).getId()) != null) {                    leaveProjectList.get(i).setChildrenProjectList(allProjectMap.get(leaveProjectList.get(i).getId()));                    //递归调用,查看子集是否还有子集                    getAllBottomProject(leaveProjectList.get(i).getChildrenProjectList(), allProjectMap);                }            }        }        return leaveProjectList;    }
/**     * 向上递归     *     * @param projectFatherList     * @param projectList     * @param projectAllList     * @throws IOException     * @throws ClassNotFoundException     */public void selectTreeUp(List<Project> projectFatherList, List<Project> projectList, List<Project> projectAllList) {        if (!StringUtils.isEmpty(projectFatherList) && projectFatherList.size() > 0) {            List<Project> projectTempList = new LinkedList<>();            for (Project k : projectFatherList            ) {
                // 如果该项目有父项目,则将父项目放入返回list(projectAllList)                if (!StringUtils.isEmpty(k.getPId())) {                    List<Project> collect = projectList.stream().filter(e -> e.getId().equals(k.getPId())).collect(Collectors.toList());                    if (collect.size() > 0) {                        projectTempList.add(collect.get(0));                    }                }            }            projectAllList.addAll(projectTempList);            projectFatherList = new LinkedList<>();            projectFatherList.addAll(projectTempList);            selectTreeUp(projectFatherList, projectList, projectAllList);        }    }    /**     * 向下递归     *     * @param projectSonList     * @param projectList     * @param projectAllList     * @throws IOException     * @throws ClassNotFoundException     */
    public void selectTreeBottom(List<Project> projectSonList, List<Project> projectList, List<Project> projectAllList) {        if (!StringUtils.isEmpty(projectSonList) && projectSonList.size() > 0) {            List<Project> projectTempList = new LinkedList<>();            List<Project> projectOrList;
            for (Project k : projectSonList            ) {
                projectOrList = projectList.stream().filter(e -> k.getId().equals(e.getPId())).collect(Collectors.toList());                projectAllList.addAll(projectOrList);                projectTempList.addAll(projectOrList);            }            projectSonList = new LinkedList<>();            projectSonList.addAll(projectTempList);            selectTreeBottom(projectSonList, projectList, projectAllList);        }    }

然后各种需求操作,即可返回一个真分页的树形结构,速度杠杠的!

补充

这样有一个问题,会导致数据无法按照创建时间排序

SELECT DISTINCT projectFullPath FROM PSAProject p LEFT JOIN SalesProject a ON a.ID= p.BusinessId  ORDER BY  t1.CreateTime DESC[42000] [Microsoft][SQL Server Native Client 10.0][SQL Server]无法绑定由多个部分组成的标识符 "t1.CreateTime"。 (4104)[42000] [Microsoft][SQL Server Native Client 10.0][SQL Server]如果指定了 SELECT DISTINCT,那么 ORDER BY 子句中的项就必须出现在选择列表中

解决方案如下:

        select p.projectFullPath ,p.CreateTime from PSAProject p where id in(        SELECT DISTINCT        projectFullPathFROM        PSAProject p        LEFT JOIN SalesProject a ON a.ID= p.BusinessId) order by p.CreateTime desc;


相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS&nbsp;SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
Web App开发SQLJava
javaweb实现分页(二)
javaweb实现分页(二)
|
Web App开发Java关系型数据库
java中部的分页实现(二)
java中部的分页实现(二)
|
SQL关系型数据库MySQL
javaweb中实现分页,持续更新……
javaweb中实现分页,持续更新……
Mybatis+mysql动态分页查询数据案例——分页工具类(Page.java)
Mybatis+mysql动态分页查询数据案例——分页工具类(Page.java)
|
SQL前端开发Java
java通用分页前端(2)
java通用分页前端(2)
9800
|
2月前
|
SQLJava数据库连接
Java中实现SQL分页的方法
无论何种情况,选择适合自己的,理解了背后的工作原理,并能根据实际需求灵活变通的方式才是最重要的。
6599
|
9月前
|
Java程序员调度
Java|PageHelper 怎么自作主张帮我分页?
没有调用 PageHelper.startPage,查询怎么也被自动分页了?
4722
|
10月前
|
Java数据处理
技术分享:高效与灵活并存——Java版通用树形结构转换工具的实现与应用
在软件开发中,树形结构的数据表现形式无处不在,从文件系统的目录树到组织架构的部门树,再到各类产品的分类结构。处理这些具有层级关系的数据时,将其转换为树形结构以便展示和操作显得尤为重要。Java作为一门成熟的编程语言,虽然提供了强大的集合框架,但并未直接提供树形结构转换的内置工具。因此,开发一个高效且灵活的通用树形结构转换工具成为许多项目中的必备需求。
22622
|
11月前
|
Java
用JAVA架建List集合为树形结构的代码方法
这段代码定义了一个表示树形结构的 `Node` 类和一个用于构建树形结构的 `TreeController`。`Node` 类包含基本属性如 `id`、`pid`、`name` 和 `type`,以及子节点列表 `children`。`TreeController` 包含初始化节点列表并将其转换为树形结构的方法。通过过滤和分组操作实现树形结构的构建。详情可见:[代码示例链接1](http://www.zidongmutanji.com/zsjx/43551.html),[代码效果参考链接2](https://www.257342.com/sitemap/post.html)。
|
算法前端开发Java
探讨Java中递归构建树形结构的算法
探讨Java中递归构建树形结构的算法
19711

热门文章

最新文章