【java实现结果集转为树结构,树转为扁平结构】

list转为树,树拉平

  • 业务需求
    • oracle实现树结构
      • 1、**Controller.java层** :前端调此处请求
      • 2、**service层:** 逻辑结构 (zbjcpjService.java),重点:this.entityMapper.queryZbjcpjTree接口
      • 3、**mapper层**:sql语句(数据库交互)(LwZbjcpjMapper.java---接口 )
      • 4、**pjpc.md文件** 某业务相关sql语句
    • pgsql实现树结构
      • 1、**Controller.java层**
      • 2、**service层**
      • 3、**mapper层**无改变,接口名不修改
      • 4、**pjpc.md文件**
    • 树其他链接

业务需求

数据库原本为oracle后转为postgresql(后续简称为pgsql),原本使用start with …connect by prior在pgsql中无法使用,转为RECURSIVE但无法达到前者父子结构排序结果集(需求:查询所有子节点),sql语句转为java代码实现。
需求:打分:小项可打分,小项的父自动计算分数,前端要显示扁平list
界面如下:
在这里插入图片描述

开发语言:
springboot+beetsql+vue

oracle实现树结构

1、Controller.java层 :前端调此处请求

/*** 获取监测指标树形*/@RequestMapping(path = "${mda.model.name}/standard/entity/pjzbtx/lwPjdx/getZbjcpjTreeList", method = RequestMethod.POST)public IPage<LwZbjcpj> getZbjcpjTreeList(@RequestBody PageDTO<LwZbjcpj, LwZbjcpjQuery> request) {return zbjcpjService.getZbjcpjTreeList(request);}

2、service层: 逻辑结构 (zbjcpjService.java),重点:this.entityMapper.queryZbjcpjTree接口

public IPage<LwZbjcpj> getZbjcpjTreeList(PageDTO<LwZbjcpj, LwZbjcpjQuery> request) {Page<LwZbjcpj> page = new Page<>();page.setCurrent(request.getPageNo());page.setSize(request.getPageSize());String pjpcdxId = request.getSimpleCondition().getPjpcdxId();List<LwZbjcpj> zbjcpjTreeList = this.entityMapper.queryZbjcpjTree(pjpcdxId);page.setTotal(zbjcpjTreeList.size());page.setRecords(zbjcpjTreeList);return page;}

3、mapper层:sql语句(数据库交互)(LwZbjcpjMapper.java—接口 )

这里的queryZbjcpjTree接口对应pjpc.md中写的sql语句命名为queryZbjcpjTree

@Mapper
@SqlResource("pjpc")
public interface LwZbjcpjMapper extends BaseExtMapper<LwZbjcpj> {public List<LwZbjcpj>  queryZbjcpjTree(@Param("pjpcdxId") String pjpcdxId);public List<String>  queryZbjcpjParentId(@Param("pjpcdxId") String pjpcdxId, @Param("id") String id);}

4、pjpc.md文件 某业务相关sql语句

queryZbjcpjTree
===
*根据批次对象id查所有子节点
with query as(select zbjc.id,zbjc.pjzb_id,zbjc.pjpcdx_id,mxzb.zbmc,mxzb.sjzb,mxzb.zbcx,zbjc.pjfs,zbjc.xzfs,zbjc.zpfsfrom lw_zbjcpj zbjcleft join lw_pjmxzb mxzbon zbjc.pjzb_id = mxzb.idwhere zbjc.pjpcdx_id = #{pjpcdxId})select t.*, level,CONNECT_BY_ISLEAF AS isleaffrom query tstart with sjzb = '0'connect by prior pjzb_id = sjzbqueryZbjcpjParentId
===
*根据批次对象id和id查所有父节点id
with query as(select zbjc.id,zbjc.pjzb_id,zbjc.pjpcdx_id,mxzb.zbmc,mxzb.sjzb,mxzb.zbcx,zbjc.pjfs,zbjc.xzfs,zbjc.zpfsfrom lw_zbjcpj zbjcleft join lw_pjmxzb mxzbon zbjc.pjzb_id = mxzb.idwhere zbjc.pjpcdx_id =  #{pjpcdxId})
select idfrom querystart with id = #{id}
connect by prior sjzb = pjzb_id

pgsql实现树结构

构造树节点类:尤其重要,树结构,关键属性:
private String id;
private String pid;
private String name;
private List<TreeNode> children;

@Data
@EqualsAndHashCode(callSuper = false)
public class ZbjcpjTreeNode {private String id;private String pjzbId;  // 子private String sjzb; // 父private String zbmc;private String pjfs;private String xzfs;private String zpfs;private int level;private int isleaf;List<ZbjcpjTreeNode> children;
}

1、Controller.java层

/*** 获取监测指标树形*/@RequestMapping(path = "${mda.model.name}/standard/entity/pjzbtx/lwPjdx/getZbjcpjTreeList", method = RequestMethod.POST)public IPage<ZbjcpjTreeNode> getZbjcpjTreeList(@RequestBody PageDTO<LwZbjcpj, LwZbjcpjQuery> request) {return zbjcpjService.getZbjcpjTreeList(request);}

2、service层

解析:getTreeNode把实体类转为有children的树结构;this.entityMapper.queryZbjcpjTreepgsql查回的具有父子关系无树形的结果集;接下来遍历结果集转为树结构(含children的list);先序遍历树即可得到扁平数据列表
treeToList树转扁平list, flattenTree先序递归,有子则继续遍历

/*** 转为树节点* @param lwZbjcpj* @return*/private ZbjcpjTreeNode getTreeNode(LwZbjcpj lwZbjcpj) {ZbjcpjTreeNode treeNode = new ZbjcpjTreeNode();try {BeanUtils.copyProperties(treeNode, lwZbjcpj);} catch (IllegalAccessException | InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();}return treeNode;}/*** 根据pjpcdxId查所有子节点  * @param request* @return*/public IPage<ZbjcpjTreeNode> getZbjcpjTreeList(PageDTO<LwZbjcpj, LwZbjcpjQuery> request) {Page<ZbjcpjTreeNode> page = new Page<>();page.setCurrent(request.getPageNo());page.setSize(request.getPageSize());String pjpcdxId = request.getSimpleCondition().getPjpcdxId();List<LwZbjcpj> zbjcpjTreeList = this.entityMapper.queryZbjcpjTree(pjpcdxId);
//	     存储  子元素Map<String, ZbjcpjTreeNode> childMap = new LinkedHashMap<>();for (LwZbjcpj zbjcpj : zbjcpjTreeList) {ZbjcpjTreeNode zbjcNode = this.getTreeNode(zbjcpj);childMap.put(zbjcpj.getPjzbId(), zbjcNode);}//	     树结构List<ZbjcpjTreeNode> tree = new ArrayList<ZbjcpjTreeNode>();for (String zbid: childMap.keySet()) {ZbjcpjTreeNode treeNode = childMap.get(zbid);if (treeNode.getSjzb() == null || "0".equals(treeNode.getSjzb())) { // 根节点tree.add(treeNode);} else { // 子节点ZbjcpjTreeNode parentNode = childMap.get(treeNode.getSjzb());if (parentNode.getChildren()==null) {parentNode.setChildren(new ArrayList<>());}parentNode.getChildren().add(treeNode);}}
//	     将树形结构转换为列表List<ZbjcpjTreeNode> flattenedList = treeToList(tree);page.setTotal(flattenedList.size());page.setRecords(flattenedList);return page;}private List<ZbjcpjTreeNode> treeToList(List<ZbjcpjTreeNode> tree) {List<ZbjcpjTreeNode> flattenedList = new ArrayList<ZbjcpjTreeNode>();for (ZbjcpjTreeNode node:tree) {
//			拉平树flattenTree(node, flattenedList);}return flattenedList;}//	递归先序遍历转为扁平数据结构private void flattenTree(ZbjcpjTreeNode node, List<ZbjcpjTreeNode> flattenedList) {flattenedList.add(node);if (node.getChildren() != null) {for(ZbjcpjTreeNode child:node.getChildren()) {flattenTree(child, flattenedList);}}}

3、mapper层无改变,接口名不修改

4、pjpc.md文件

queryZbjcpjTreequeryZbjcpjParentId两个pgsql语句

queryZbjcpjTree
===
*根据批次对象id查所有子节点  
WITH RECURSIVE query AS (SELECT zbjc.id,zbjc.pjzb_id,zbjc.pjpcdx_id,mxzb.zbmc,mxzb.sjzb,mxzb.zbcx,zbjc.pjfs,zbjc.xzfs,zbjc.zpfsFROM lw_zbjcpj zbjcLEFT JOIN lw_pjmxzb mxzb ON zbjc.pjzb_id = mxzb.idWHERE zbjc.pjpcdx_id = #{pjpcdxId}
),
tree AS (SELECT t.*, 1 AS levelFROM query tWHERE sjzb = '0'UNION ALLSELECT q.*, tree.level + 1FROM query qJOIN tree ON q.sjzb = tree.pjzb_id
)
SELECT tree.*, CASE WHEN EXISTS (SELECT 1 FROM query q WHERE q.sjzb = tree.pjzb_id) THEN 0 ELSE 1 END AS isleafFROM tree;queryZbjcpjParentId
===
*根据批次对象id和id查所有父节点id
WITH RECURSIVE query AS (SELECT zbjc.id,zbjc.pjzb_id,zbjc.pjpcdx_id,mxzb.zbmc,mxzb.sjzb,mxzb.zbcx,zbjc.pjfs,zbjc.xzfs,zbjc.zpfsFROM lw_zbjcpj zbjcLEFT JOIN lw_pjmxzb mxzb ON zbjc.pjzb_id = mxzb.idWHERE zbjc.pjpcdx_id = #{pjpcdxId}
),
tree AS (SELECT id, pjzb_id, sjzbFROM queryWHERE id = #{id}UNION ALLSELECT q.id, q.pjzb_id, q.sjzbFROM query qJOIN tree ON q.pjzb_id = tree.sjzb
)
SELECT id FROM tree;

queryZbjcpjTree的结果集为:level为1在一起,level为2气候,依次往后排,无法达到oracle使用start with…connect by prior就能达到排序的效果,因此使用java代码实现扁平数据树形展示
在这里插入图片描述
总结:俩要点,第一:结果集转为带children的树结构;第二:将树转为list扁平结构;算法使用到递归与迭代。

树其他链接

前后端构建侧边栏多级动态导航栏—树形结构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/45142.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【python算法学习1】用递归和循环分别写下 fibonacci 斐波拉契数列,比较差异

问题&#xff1a; fibonacci 斐波拉契数列&#xff0c;用递归和循环的方法分别写,比较递归和循环的思路和写法的差别 最直接的思路&#xff0c;是写递归方法 循环方法的稍微有点绕&#xff0c;我觉得问题主要是出在&#xff0c;总结循环的通项公式更麻烦&#xff0c;难在数学…

多目标螳螂搜索算法MOMSA求解无人机三维路径规划,可以自行修改障碍物位置(MATLAB代码)

无人机路径规划多目标优化求解是一个复杂的过程&#xff0c;涉及到多个目标的考量和优化算法的应用。以下是一些关键点和相关算法的概述&#xff1a; 1. **多目标优化策略**&#xff1a;在无人机路径规划中&#xff0c;需要同时考虑多个目标&#xff0c;如路径长度、安全性、飞…

关于delete和delete[ ]混用的未定义问题解释

我们知道delete用于释放一个动态空间&#xff0c;而delete[ ]用于释放多个动态空间&#xff0c;但是如果我们混用的话会导致什么问题&#xff1f;我在博客上看了许多文章&#xff0c;但不尽人意&#xff0c;因此写下这篇文章让你知其然知其所以然&#xff08;浅薄的解释&#x…

大数据学习之Spark基础

Spark基础 简述 1、spark作业执行的特点&#xff1a; &#xff08;1&#xff09;只有遇到行动算子的时候&#xff0c;整个spark作业才会被触发执行 &#xff08;2&#xff09;遇到几次&#xff0c;执行几次 2、RDD: 弹性分布式数据集 弹性&#xff1a;数据量可大可小 RDD类似…

插片式远程 I/O模块:Profinet总线耦合器在SIMATIC Manager配置

XD9000是Profinet总线耦合器&#xff0c;单个耦合器最多可扩展32个I/O模块&#xff01;本文将详细介绍如何在SIMATIC Manager中配置插片式远程 I/O模块的Profinet总线耦合器&#xff0c;帮助您更好地应用这一技术。 一、SIMATIC Manager软件组态步骤&#xff1a; 1、创建工程&…

什么是敏捷本地化

快速、敏捷的多语言产品和服务交付正逐渐成为众多行业的常态。在这种情况下&#xff0c;重点从传统的期望&#xff08;即在合理的时间框架内翻译大量内容&#xff09;转变为翻译工作量非常大的小片段&#xff0c;通常在2-3到12-24小时之间&#xff0c;通常在周末或假期。 Logr…

IntelliJ IDEA自定义菜单(Menus)、任务栏(toolbars)详细教程

一、自定义菜单 1、打开Settings&#xff0c;找到Menus and Toolbars 2、点击右边的Main Menu&#xff0c;点击号&#xff0c;选择Add Action 3、弹出Add Action弹窗&#xff0c;搜索或者选择你要添加的指令 二、自定义工具栏 1、右键IDEA上方的工具栏空白位置&#xff0c;选…

计算机网络体系结构解析

OSI参考模型 与 TCP/IP模型 如图所示 TCP/IP模型有几层 应用层&#xff1a;只需要专注于为用户提供应用功能 HTTP、SMTP、Telnet等&#xff0c;工作在操作系统中的用户态&#xff0c;传输层及以下工作在内核态传输层&#xff1a;为应用层提供网络支持&#xff08;TCP、UDP传…

vue3实现在style中使用响应式变量

vue2的时候需要在style模块中访问script模块中的响应式变量&#xff0c;为此不得不使用css变量去实现。现在vue3已经内置了这个功能啦&#xff0c;可以在style中使用v-bind指令绑定script模块中的响应式变量。 示例 <template><div><span>hello </span&…

40个高阶ChatGPT学术论文指令集(附GPT使用链接)

我精心挑选的40个顶尖ChatGPT学术论文指令集&#xff0c;无疑将成为你撰写论文和开展研究的珍贵资源&#xff0c;极力推荐你珍藏起来&#xff01;这些建议极具实用价值&#xff0c;能有效提高你的研究工作效率&#xff0c;使得论文撰写过程轻松许多。 在开始前&#xff0c;提示…

8、matlab彩色图和灰度图的二值化算法汇总

1、彩色图和灰度图的二值化算法汇总原理及流程 彩色图和灰度图的二值化算法的原理都是将图像中的像素值转化为二值&#xff08;0或1&#xff09;&#xff0c;以便对图像进行简化或者特定的图像处理操作。下面分别介绍彩色图和灰度图的二值化算法的原理及流程&#xff1a; 1&a…

Python功能制作之获取CSDN所有发布文章的对应数据

大家好&#xff0c;今天我要分享的是一个实用的Python脚本&#xff0c;它可以帮助你批量获取CSDN博客上所有发布文章的相关数据&#xff0c;并将这些数据保存到Excel文件中。此外&#xff0c;脚本还会为每篇文章获取一个质量分&#xff0c;并将这个分数也记录在Excel中。让我们…

多周期路径的约束与设置原则

本节将回顾工具检查建立保持时间的原则&#xff0c;接下来介绍设置多周期后的检查原则。多周期命令是设计约束中常用的一个命令&#xff0c;用来修改默认的建立or保持时间的关系。基本语法如下 默认的建立时间与保持时间的检查方式 DC工具计算默认的建立保持时间关系是基于时钟…

Python实战:拥有设闹钟功能的可视化动态闹钟的实现

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

6-5,web3浏览器链接区块链(react+区块链实战)

6-5&#xff0c;web3浏览器链接区块链&#xff08;react区块链实战&#xff09; 6-5 web3浏览器链接区块链&#xff08;调用读写合约与metamask联动&#xff09; 6-5 web3浏览器链接区块链&#xff08;调用读写合约与metamask联动&#xff09; 这里就是浏览器端和智能合约的交…

高职Web全栈式开发实训室解决方案

一、专业背景 随着网络普及和发展&#xff0c;网站作为一种很强大的工具和平台愈来愈融入了人们的生活&#xff0c;而与用户关系最密切的前端技术也逐渐获得应有的重视。咱们能够看到前端重构的行业发展潜力巨大&#xff0c;各大知名的网络公司对前端人才的求饥若渴。近年来HT…

DID差分模型案例集(传统DID、队列DID、渐近DID、空间DID、PSM-DID)

双重差分&#xff08;DID&#xff09;模型是一种广泛应用于经济学、社会学等领域的统计方法&#xff0c;主要用于评估政策或事件的因果效应。以下是DID模型几个重要变体的简要介绍&#xff1a; 1、传统DID&#xff08;Traditional DID&#xff09;&#xff1a;这是DID模型的基…

【Qt 从基础】创建一个 Qt 项目后,自动生成的代码和文件分析

文章目录 1. Sources 目录下&#xff0c;main.cpp 文件的分析&#x1f427;2. Headers 目录下&#xff0c;widget.h 文件的分析&#x1f427;3. Sources 目录下&#xff0c;widget.cpp 文件的分析&#x1f427;4. Forms 目录下&#xff0c;widget.ui 文件的分析&#x1f427;5.…

目标检测基本标注工具-labelImg安装与使用

&#x1f349;一、安装 1.1 打开conda创建虚拟环境&#x1f388; conda create -n labelImg python3.8 -y 1.2 激活labelImg虚拟环境&#x1f388; activate labelImg1.3 安装labelImg&#x1f388; pip install -i https://pypi.tuna.tsinghua.edu.cn/simple lab…

Protobuf: 大数据开发中的高效数据传输利器

作为一名大数据开发者&#xff0c;我经常需要处理海量的数据传输和存储。在这个过程中&#xff0c;选择一个高效、可靠的数据序列化工具至关重要。今天&#xff0c;我想和大家分享一下我在项目中使用 Protobuf 的经历。 目录 故事背景Protobuf 简介优点&#xff1a; 实战案例示…