sql中使用collection返回集合数据

news2025/1/11 16:52:47

        今天在写一个接口时,有两级目录(父子关系),接口需要把两级数据以嵌套的形式返回给前端。我这个新手菜鸟一上来就查询两次sql,然后业务中处理嵌套关系,事实这种方法也能达到目的。但主管PR代码时,问为啥不在sql语句中处理呢?我当然不知道还有这种骚操作,下面是在主管的指导下改造的通过sql语句实现的,记录下来慢慢欣赏。

1、先理一下表中的数据结构

①project_case表,其中有个数组类型字段category_id_list,用来记录此条数据对应的二级目录

②project_case_category表,其中parent_id为0表示一级目录,其他则为二级目录

2、sql中实现代码

<resultMap id="ProjectCaseCategoryVo" type="com.hikvision.idatafusion.dhidata.bean.vo.projectcase.ProjectCaseCategoryVo">
    <result column="first_category_id" jdbcType="BIGINT" property="id"/>
    <result column="first_category_name" jdbcType="VARCHAR" property="categoryName"/>
    <collection property="children" ofType="com.hikvision.idatafusion.dhidata.bean.vo.projectcase.ProjectCaseCategoryVo" javaType="java.util.List">
        <result property="id" column="second_category_id" jdbcType="INTEGER"/>
        <result property="categoryName" column="second_category_name" jdbcType="VARCHAR"/>
    </collection>
</resultMap>

<select id="getListFront" resultMap="ProjectCaseCategoryVo">
    select first_category.id as first_category_id, first_category.category_name as first_category_name,
           second_category.id as second_category_id, second_category.category_name as second_category_name
    from (
         select distinct unnest(category_id_list) as category_id from project_case where delete_flag = 0 and publish_state = '1'
         ) t
    left join project_case_category second_category on second_category.id  = t.category_id
    left join project_case_category first_category on first_category.id  = second_category.parent_id
    where second_category.delete_flag = 0 and first_category.delete_flag = 0
    order by first_category.category_sort desc, second_category.category_sort desc
</select>

上面的sql写的时候要注意两点:①property要和实体类中的属性对应,比如id、categoryName、children都是实体类中的字段;②column要和数据库中的字段保持一致,比如first_category_id、first_category_name等,都是sql语句查询出来后重命名的字段。

3、sql中对应的实体类代码

①ProjectCaseCategoryVo

@Data
@ToString
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class ProjectCaseCategoryVo extends ProjectCaseCategory implements Serializable {
    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "同一类型的案例")
    private List<ProjectCaseCategory> projectCaseVoList;


    @ApiModelProperty(value = "子分类")
    private List<ProjectCaseCategoryVo> children = new ArrayList<>();
}

②ProjectCaseCategory

@Data
@ToString
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class ProjectCaseCategory extends AbstractEntity {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty("分类名称")
    private String categoryName;

    @ApiModelProperty("分类排序")
    private Integer categorySort;

    @ApiModelProperty(value = "父节点ID")
    public Long parentId;
}

4、sql中处理后,业务层的代码就简单了,查询后直接返回给前端便可

List<ProjectCaseCategory> list = projectCaseCategoryDao.getListFront(dto);
List<ProjectCaseCategoryVo> projectCaseCategoryVos = BeanUtil.copyProperties(list, ProjectCaseCategoryVo.class);
return projectCaseCategoryVos;

5、此时返回给前端的数据格式正是想要的

6、业务代码中有个工具类BeanUtil,是在实体类转换工具BeanUtils基础上封装的

public class BeanUtil extends BeanUtils {

    /**
     * copy 对象
     *
     * @param sourceList
     * @param targetClazz
     * @param <T>
     * @return
     */
    public static <T> List<T> copyProperties(List<?> sourceList, Class<T> targetClazz) {
        List<T> resultList = new ArrayList<T>();
        if (CollectionUtils.isEmpty(sourceList)) {
            return resultList;
        }
        for (Object object : sourceList) {
            try {
                T target = targetClazz.newInstance();
                copyProperties(object, target);
                resultList.add(target);
            } catch (Exception e) {
                log.error("copyProperties fail", e);
                throw new BusinessException(ErrorCodes.OBJECT_CLONE_FAIL);
            }
        }
        return resultList;
    }

    /**
     * copy 对象
     *
     * @param source
     * @param targetClazz
     * @param <T>
     * @return
     */
    public static <T> T copyProperties(Object source, Class<T> targetClazz) {
        if (source == null) {
            return null;
        }
        T target = null;
        try {
            target = targetClazz.newInstance();
            copyProperties(source, target);
        } catch (Exception e) {
            log.error("copyProperties fail", e);
            throw new BusinessException(ErrorCodes.OBJECT_CLONE_FAIL);
        }
        return target;
    }

    /**
     * 判断对象的所有属性是否都为空
     * @param object
     * @return
     * @throws IllegalAccessException
     */
    public static boolean checkFieldAllNull(Object object, List<String> ignoreProperties) {
        for (Field f : object.getClass().getDeclaredFields()) {
            if (ignoreProperties != null && ignoreProperties.contains(f.getName())) {
                continue;
            }
            f.setAccessible(true);
            if (Modifier.isFinal(f.getModifiers()) && Modifier.isStatic(f.getModifiers())) {
                continue;
            }
            try {
                if (!isEmpty(f.get(object))) {
                    System.out.println(f.getName());
                    return false;
                }
            } catch (Exception e) {
                return false;
            }
            f.setAccessible(false);
        }
        //父类public属性
        for (Field f : object.getClass().getFields()) {
            if (ignoreProperties != null && ignoreProperties.contains(f.getName())) {
                continue;
            }
            f.setAccessible(true);
            if (Modifier.isFinal(f.getModifiers()) && Modifier.isStatic(f.getModifiers())) {
                continue;
            }
            try {
                if (!isEmpty(f.get(object))) {
                    return false;
                }
            } catch (Exception e) {
                return false;
            }
            f.setAccessible(false);
        }
        return true;
    }

    @SuppressWarnings("rawtypes")
    private static boolean isEmpty(Object object) {
        if (object == null) {
            return true;
        } else if (object instanceof String && (object.toString().equals(""))) {
            return true;
        } else if (object instanceof Collection && ((Collection) object).isEmpty()) {
            return true;
        } else if (object instanceof Map && ((Map) object).isEmpty()) {
            return true;
        } else if (object instanceof Object[] && ((Object[]) object).length == 0) {
            return true;
        }
        return false;
    }
}

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

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

相关文章

【自动驾驶可视化工具】

自动驾驶可视化工具 自动驾驶可视化工具1.百度Apollo的Dreamview:2.Cruise的Worldview:3.Uber的AVS:4.Fglovex Studio: 自动驾驶可视化工具 介绍一下当前主流的自动驾驶可视化工具。 1.百度Apollo的Dreamview: Dreamview是百度Apollo平台开发的一种可视化工具&#xff0c;用…

华为配置中心AP内漫游实验

华为配置中心AP内漫游示例 组网图形 图1 配置中心AP内漫游组网图 配置流程组网需求配置思路数据规划配置注意事项操作步骤配置文件 配置流程 WLAN不同的特性和功能需要在不同类型的模板下进行配置和维护&#xff0c;这些模板统称为WLAN模板&#xff0c;如域管理模板、射频模…

K8S日志收集方案-EFK部署

EFK架构工作流程 部署说明 ECK (Elastic Cloud on Kubernetes)&#xff1a;2.7 Kubernetes&#xff1a;1.23.0 文件准备 crds.yaml 下载地址&#xff1a;https://download.elastic.co/downloads/eck/2.7.0/crds.yaml operator.yaml 下载地址&#xff1a;https://download.e…

javaweb-maven+HTTP协议+Tomcat+SpringBoot入门+请求+响应+分层解耦

Maven IDEA集成Maven 依赖管理 依赖配置 maven是插件完成对应的工作的~ 哇哇哇maven看完啦~~~~~~ Spring.io Springboot是Spring家族的子项目&#xff0c;可以帮助我们非常快速地构建应用程序&#xff0c;简化开发&#xff0c;提高效率。 RestController请…

【XR806开发板试用】基于WEBSOCKET实现人机交互(控制开关灯)以及开发问题记录

一、开发板编译、功能介绍 根据官方文档编译烧录成功后&#xff0c;我们修改下官方例子&#xff0c;进行开发来实现websocket。 整体流程&#xff1a;开发板先自动寻找指定的wifi并且连接&#xff0c;连接成功后&#xff0c;通过websocket来与服务端连接&#xff0c;连接成功后…

升入理解计算机系统学习笔记

磁盘存储 磁盘是广为应用的保存大量数据的存储设备&#xff0c;存储数据的数量级可以达到几百到几千千兆字节&#xff0c;而基于RAM的存储器只能有几百或几千兆字节。不过&#xff0c;从磁盘上读信息的时间为毫秒级&#xff0c;比从DRAM读慢了10万倍&#xff0c;比从SRAM读慢了…

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:GridItem)

网格容器中单项内容容器。 说明&#xff1a; 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。仅支持作为Grid组件的子组件使用。 子组件 可以包含单个子组件。 接口 GridItem GridItem(value?: GridItemOptions)…

DVWA靶场-CSRF跨站请求伪造

CSRF(跨站请求伪造)简介概念 CSRF&#xff08;Cross—site request forgery&#xff09;&#xff0c;跨站请求伪造&#xff0c;是指利用受害者未失效的身份认证信息&#xff08;cookie&#xff0c;会话等&#xff09;&#xff0c;诱骗其点击恶意链接或者访问包含攻击代码的页面…

UG NX二次开发(C#)-单选对话框UF_UI_select_with_single_dialog的使用

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1、前言2、UF_UI_select_with_single_dialog函数3、实现代码3.1 利用委托创建一个方法3.2 直接调用1、前言 对于单选对话框,采用C++/C写的时候比较容易,也在帮助文档中有示例,但是对于C#开发采…

修复ElementUI中el-select与el-option无法通过v-model实现数据双向绑定的问题

1. 问题描述 需求&#xff1a;在使用ElementUI时&#xff0c;通过el-select和el-option标签实现下拉列表功能&#xff0c;当el-option中的选项被选中时&#xff0c;被选中的选项可以正确回显到已选择的列表中。 对于上面的下拉列表&#xff0c;当我们选中“超级管理员”的选项…

小程序路由跳转---事件通信通道EventChannel(一)

EventChannel是什么&#xff1f; 借助wx.navigateTo方法&#xff0c;在两个页面之间构建起数据通道&#xff0c;互相可以通过“派发事件”及“注册事件监听器”来实现基于事件的页面通信。基础库版本v2.7.3以上支持。 EventChannel中主要的方法 EventChannel.emit( strign e…

【四 (3)数据可视化之 Seaborn 常用图表及代码实现 】

目录 文章导航一、介绍二、安装Seaborn三、导入Seaborn四、设置可以中文显示五、占比类图表1、饼图2、环形图 六、比较排序类1、条形图2、箱线图3、小提琴图 七、趋势类图表1、折线图 八、频率分布类1、直方图 九、关系类图表1、散点图2、成对关系图3、热力图 文章导航 【一 简…

手机备忘录怎么导出到电脑,如何将手机备忘录导出到电脑

备忘录是我们日常生活和工作中常用的工具之一&#xff0c;我们可以在手机上轻松地记录重要的事务、想法和灵感。然而&#xff0c;在某些情况下&#xff0c;我们可能需要将手机备忘录导出到电脑进行更详细的整理和管理。那么&#xff0c;手机备忘录怎么导出到电脑&#xff0c;如…

ASP.NET-Server.HtmlEncode

目录 背景: 1.转义特殊字符&#xff1a; 2.防止跨站脚本攻击&#xff08;XSS&#xff09;&#xff1a; 3.确保输出安全性&#xff1a; 4.保留原始文本形式&#xff1a; 5.与用户输入交互安全&#xff1a; 实例说明: 不用Server.HtmlEncode 效果展示: 用Server.HtmlEnc…

【Numpy】练习题100道(26-50题)

#学习笔记# 在学习神经网络的过程中发现对numpy的操作不是非常熟悉&#xff0c;遂找到了Numpy 100题。 Git-hub链接 1.题目列表 26. 下面的脚本输出什么&#xff1f;(★☆☆) print(sum(range(5),-1)) from numpy import * print(sum(range(5),-1)) 27. 考虑一个整数向量…

TCP的三次握手和4次挥手

一、首先讲一下TCP的由来 最开始&#xff0c;人们考虑到将网络信息的呼唤与回应进行规范&#xff0c;达成一种公认的协议&#xff0c;就好像没有交通规则的路口设定交通规则。 人们设计出完美的OSI协议&#xff0c;这个协议包含七个层次由下到上分别是&#xff1a; 物理层&…

【Unity】进度条和血条的三种做法

前言 在使用Unity开发的时候&#xff0c;进度条和血条是必不可少的&#xff0c;本篇文章将简单介绍一下几种血条的制作方法。 1.使用Slider Slider组件由两部分组成&#xff1a;滑动区域和滑块。滑动区域用于显示滑动条的背景&#xff0c;而滑块则表示当前的数值位置。用户可…

因聚而生 数智有为丨软通动力携子公司鸿湖万联亮相华为中国合作伙伴大会2024

3月14日&#xff0c;以“因聚而生 数智有为”为主题的“华为中国合作伙伴大会2024”在深圳隆重开幕。作为华为的重要合作伙伴和本次大会钻石级&#xff08;最高级&#xff09;合作伙伴&#xff0c;软通动力深度参与本次盛会&#xff0c;携前沿数智化技术成果和与华为的联合解决…

Python之Web开发中级教程----创建Django子应用

Python之Web开发中级教程----创建Django子应用 基于上一个教程的Django项目&#xff08;可以先看上一集&#xff0c;链接如下&#xff1a;&#xff09; https://mp.csdn.net/mp_blog/creation/editor/136724897 2.创建子应用 python manager.py startapp book admin.py&…

蓝桥杯 EDA 组 2021-2022 省赛真题+模拟题原理图解析

本文解析了标题内的原理图蓝桥杯EDA组真题&#xff0c;为方便阅读2023年真题/模拟和国赛部分放到其他章节解析。下文中重复或者是简单的电路节约篇幅不在赘述。 其中需要补充和计算原理图的题目解析都放在最下面 一、2021第十二届真题第一场 1.1 AMS1117 线性稳压器 最常见的1…