springboot注解开发如何映射对象型数据

创作灵感

最近在帮学校写一款小程序时,有这样一个数据需要展示:一条申请记录,里面包含了申请时间、申请状态、申请所提供的六条活动记录等待,其中,申请所提供的六条活动记录为一个数组,数组中的每个元素又为一个对象。

那么,对于这样的一个对象,我们又该如何将其从数据库中映射为一个java对象呢?这里需要注意的是,数据库的表设计与java中的实体类其实是有着非常大的差距的,例如,我们的数据库因为需要满足一些范式需求;在我的数据库内,上面这个对象信息主要存放在三个表内,一个是申请表,其中包含了用户id,六次活动记录的id与申请时间等、一个是用户表,存放了用户的基本信息、一个是活动记录表,这个表内包含了哪个用户参加了哪次活动(其实就是用户id和活动id)。

但是在java实体类对象内,我们要的可不是这条申请记录里面的六次活动记录的id

第一种写法(错误示例)

之所以将第一种写法视为错误示例,并不是说第一种写法会出现BUG,而是说第一种写法违背了我们分层的思想,下面先分享一下我的第一种写法:

@Override
    public ApplyRecord[] getApplyRecords() {
        ApplyRecord[] applyRecords=applyRecordMapper.getApplyRecords();
        for (ApplyRecord applyRecord : applyRecords) {
            User user= userMapper.getAllById(applyRecord.getUserId());
            applyRecord.setName(user.getName());
            ActivityRecord[] activityRecords = new ActivityRecord[6];
            ActivityRecord activityRecordOne=activityRecordMapper.getActivityRecordById(
                    applyRecord.getActivityRecordIdOne());//获取申请素拓记录中提交的六次活动记录
            ActivityRecord activityRecordTwo=activityRecordMapper.getActivityRecordById(
                    applyRecord.getActivityRecordIdTwo());//获取申请素拓记录中提交的六次活动记录
            ActivityRecord activityRecordThree=activityRecordMapper.getActivityRecordById(
                    applyRecord.getActivityRecordIdThree());//获取申请素拓记录中提交的六次活动记录
            ActivityRecord activityRecordFour=activityRecordMapper.getActivityRecordById(
                    applyRecord.getActivityRecordIdFour());//获取申请素拓记录中提交的六次活动记录
            ActivityRecord activityRecordFive=activityRecordMapper.getActivityRecordById(
                    applyRecord.getActivityRecordIdFive());//获取申请素拓记录中提交的六次活动记录
            ActivityRecord activityRecordSix=activityRecordMapper.getActivityRecordById(
                    applyRecord.getActivityRecordIdSix());//获取申请素拓记录中提交的六次活动记录
            Activity activityOne=activityMapper.getAllById(activityRecordOne.getActivityId());
            activityRecordOne.setName(activityOne.getName());
            activityRecordOne.setDate(activityOne.getDate());
            Activity activityTwo=activityMapper.getAllById(activityRecordTwo.getActivityId());
            activityRecordTwo.setName(activityTwo.getName());
            activityRecordTwo.setDate(activityTwo.getDate());
            Activity activityThree=activityMapper.getAllById(activityRecordThree.getActivityId());
            activityRecordThree.setName(activityThree.getName());
            activityRecordThree.setDate(activityThree.getDate());
            Activity activityFour=activityMapper.getAllById(activityRecordFour.getActivityId());
            activityRecordFour.setName(activityFour.getName());
            activityRecordFour.setDate(activityFour.getDate());
            Activity activityFive=activityMapper.getAllById(activityRecordFive.getActivityId());
            activityRecordFive.setName(activityFive.getName());
            activityRecordFive.setDate(activityFive.getDate());
            Activity activitySix=activityMapper.getAllById(activityRecordSix.getActivityId());
            activityRecordSix.setName(activitySix.getName());
            activityRecordSix.setDate(activitySix.getDate());
            activityRecords[0]=activityRecordOne;
            activityRecords[1]=activityRecordTwo;
            activityRecords[2]=activityRecordThree;
            activityRecords[3]=activityRecordFour;
            activityRecords[4]=activityRecordFive;
            activityRecords[5]=activityRecordSix;
            applyRecord.setActivityRecords(activityRecords);
        }
        return applyRecords;
    }

相信大家看到这段代码的时候,眼睛都花了,这里我并没有将DAO层的操作展现给大家,但是大家在看到我的调用应该基本都明白。无非就是拿到了指定活动的id然后去获取该活动的信息等等。但是,这种事情不应该是在DAO层要全部完成的吗?这就是我吃了没文化的亏!

在最近上课时,听到了老师说到了关于这样的对象,我们在设计java实体类时,应该存放的是具体的对象,而非这个对象的id。

在升级这个小程序时,我遇到了一个类似的功能,也是查询这样的一系列数据,下面向大家展示一下正确的做法

第二种写法(正确示例)

如果要将上述对象进行一个完整的映射,那么我们就需要用到结果集映射了。因为我使用的是注解开发,下面为我的DAO层操作:

@Select("SELECT * FROM applyRecord WHERE userId=#{userId} ORDER BY date DESC LIMIT #{start},10")
    @Results({
            @Result(column = "date",property = "date"),//申请时间
            @Result(column = "status",property = "status"),//申请状态
            @Result(
                    column = "userId",
                    property = "user",
                    javaType= User.class,
                    one = @One(select="org.example.Mapper.UserMapper.getAllById")
            ),
            @Result(
                    column = "activityRecordIdOne,activityRecordIdOne,activityRecordIdTwo,activityRecordIdTwo," +
                            "activityRecordIdThree,activityRecordIdThree,activityRecordIdFour,activityRecordIdFour," +
                            "activityRecordIdFive,activityRecordIdFive,activityRecordIdSix,activityRecordIdSix",
                    property = "activityRecords",
                    javaType = ActivityRecord[].class,
                    many = @Many(select = "org.example.Mapper.ActivityRecordMapper.getActivityRecordsInIds")
            )
    })
    ApplyRecord[] getApplyRecordsByUserId(@Param("userId") Integer userId,@Param("start") Integer start);

ApplyRecordMapper文件

@Select("SELECT * FROM (activityRecord,activity) WHERE activityRecord.id IN (#{activityRecordIdOne}," +
            "#{activityRecordIdTwo},#{activityRecordIdThree},#{activityRecordIdFour},#{activityRecordIdFive}," +
            "#{activityRecordIdSix}) AND activity.id=activityRecord.activityId")
    ActivityRecord[] getActivityRecordsInIds(@Param("activityRecordIdOne") Integer activityRecordIdOne,
                                             @Param("activityRecordIdTwo") Integer activityRecordIdTwo,
                                             @Param("activityRecordIdThree") Integer activityRecordIdThree,
                                             @Param("activityRecordIdFour") Integer activityRecordIdFour,
                                             @Param("activityRecordIdFive") Integer activityRecordIdFive,
                                             @Param("activityRecordIdSix") Integer activityRecordIdSix);

ActivityRecordMapper文件

上面的两个文件,是不是感觉比第一种方法更加易懂?我们主要需要看懂的就是第一个文件,其中,普通类型的映射只需要column与property两个属性映射就好了,但如果碰上了需要映射一个对象,我们就需要用到@One这个注解,这个注解后面的select是一个方法的地址。同时需要注意的是,javaType表示的是这个属性的类,下面的@Maney类似,但不同的是,这个注解查询出来的是多个值。

难点解释

相信大家在看我的代码还看到了我在many的那个result中,传递column参数时,传递了不止一个参数,但是每个参数都传递了两边?其实我并没有传递两边,这就好像我们在使用get方法传递参数一样,时以键值对的方式进行传递的。只不过我的键与值都是同样的名字而已。

下面给大家展示一下我的最终效果吧!

 这就是一条申请记录,里面包含了学生信息,以及六条活动记录信息!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

面板数据门槛归回分析,xthreg的安装,xthreg2安装包

我用的是Stata17,数据是不平衡的面板数据,需要用到xthreg2,虽然我找到了xthreg2.ado,但是还需要安装xthreg,因为运行xthreg2需要xthreg包顺带安装的lxthreg.mlib文件。但是!我后来发现还是不行,最后是去买了一个真正能用到xthreg2的lxthreg.mlib文件,才可以运行。 一、…

[图解]软件开发中的糊涂用语-04-为什么要追究糊涂用语

0 00:00:00,030 --> 00:00:05,620 今天呢,我们来说一个为什么要追究糊涂用语的问题 1 00:00:06,310 --> 00:00:06,548 2 00:00:06,548 --> 00:00:11,077 大家知道我们前些天都发了好几个视频 3 00:00:11,077 --> 00:00:13,461 追究这个糊涂用语 4 00…

2024免费专为Mac用户设计的清理和优化工具CleanMyMac X

CleanMyMac X是一款专为Mac用户设计的清理和优化工具。以下是对CleanMyMac X的详细介绍: 一、主要功能 系统清理:CleanMyMac X能够智能扫描Mac的磁盘空间,识别并清理各种垃圾文件,这些垃圾文件包括重复文件、无用的语言安装包、i…

五.音视频编辑-音频混合-应用

引言 音频混合技术是一项强大的工具,可以为应用程序增添丰富的功能和用户体验。在前一篇博客中,我们深入探讨了AVFoundation框架中的音频混合基础知识和实现方法。现在,让我们进一步探索,看看如何将这些技术应用到实际项目中。 …

Django项目无法安装python-ldap依赖解决方案

最近工作中安排了一个Python web项目,使用Pycharm从git拉取代码后,配置号Python的解释器和pip后,Pycharm自动下载安装项目所需的依赖,但是有一个依赖django-auth-ldap4.1.0安装始终失败,最初的异常信息提示是&#xff…

Java客户端如何直接调用es的API

Java客户端如何直接调用es的API 一. 问题二. withJson 前言 这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。 作者:神的孩子都在歌唱 一. 问题 今天做项目的时候,想要直接通过java客户端调用es的api…

解决Django中调页面时出现“Did you forget to register or load this tag”报错

解决Django中调页面时出现“Did you forget to register or load this tag?”报错 1.问题收录 2.分析问题 在HTML文件中,{{title}},{{lanyy}},django 默认规定的语法,用{{}}包起来的变量叫做模板变量。 django渲染模板时会将大…

2.1K Star微软开源的高质量 iot库

功能描述 该项目是一个开源的 .NET Core 实现,旨在帮助开发者构建适用于物联网(IoT)设备和场景的应用程序。它提供了与传感器、显示器和输入设备等相互作用所需的 GPIO 引脚、串口等硬件的接口。该仓库包含 System.Device.Gpio 库以及针对各种板卡(如 Ra…

论文笔记:Time-LLM: Time Series Forecasting by Reprogramming Large Language Models

iclr 2024 reviewer 评分 3888 1 方法 提出了 Time-LLM, 是一个通用的大模型重编程(LLM Reprogramming)框架将 LLM 轻松用于一般时间序列预测,而无需对大语言模型本身做任何训练 为什么需要时序数据和文本数据对齐:时…

vi, vim,data,wc,系统常用命令-读书笔记(十)

vi 文本编辑器 基本上 vi 共分为三种模式,分别是“一般指令模式”、“编辑模式”与“命令行命令模式”。这三种模式的作用分别是: 一般指令模式(command mode)以 vi 打开一个文件就直接进入一般指令模式了(这是默认的…

分类预测 | Matlab实现CNN-LSTM-SAM-Attention卷积长短期记忆神经网络融合空间注意力机制的数据分类预测

分类预测 | Matlab实现CNN-LSTM-SAM-Attention卷积长短期记忆神经网络融合空间注意力机制的数据分类预测 目录 分类预测 | Matlab实现CNN-LSTM-SAM-Attention卷积长短期记忆神经网络融合空间注意力机制的数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Mat…

frp改造Windows笔记本实现家庭版免费内网穿透

文章目录 前言frp原理Windows服务端IP检验IP固定软件下载端口放行端口映射开机启动 NAS客户端端口查询软件下载端口检验穿透测试自启设置 Ubuntu客户端软件下载后台启动 后记 前言 之前一直用花生壳远程控制一个服务器,但最近内网的网络策略似乎发生了变化&#xf…

java中的异常机制

异常原理分析 在我们编写一个代码的时候必然会出现这样那样的问题,这些问题可能是明显的,也有可能是不明显的。从理论上来说,一个程序员应当具备处理代码出现的大多数问题的能力,但是这并不意味着程序员要思考处理所有的代码问题。…

硬盘日常使用中的注意事项

硬盘是计算机中的重要存储设备,负责存储大量的数据。为了确保数据的完整性和硬盘的寿命,日常使用中需要注意以下几点: 避免震动和撞击:硬盘在工作时,内部的磁盘正在高速旋转,任何轻微的震动或撞击都可能导致磁盘损坏或数据丢失。因此,使用硬盘时应确保计算机放置稳定,避…

Python图像处理【24】面部变形(face morphing)

面部变形 0. 前言1. 网格变形算法2. 实现面部变形小结系列链接 0. 前言 面部变形 (face morphing) 的目的是在计算图像中两个面部之间的平均值,它并不是计算两张图像的平均值,而是计算面部区域的平均值。可以将该过程分解为以下两步: 对齐两…

Docker容器化部署(企业版)

大家好,webfunny前端监控埋点系统,已经正式发布了webfunny的官方镜像: Webfunny镜像目录:https://hub.docker.com/r/webfunny/webfunny_monitor_cluster/tags 部署前提是你的服务器已经安装了Docker环境,没有安装doc…

车载电子电器架构 —— 售后诊断开发

车载电子电器架构 —— 售后诊断开发 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己…

OpenCV——Niblack局部阈值二值化方法

目录 一、Niblack算法1、算法概述2、参考文献二、代码实现三、结果展示OpenCV——Niblack局部阈值二值化方法由CSDN点云侠原创,爬虫自重。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、Niblack算法 1、算法概述 Niblack 算法是一种典型的局部阈值…

SpringMVC深解--一起学习吧之架构

SpringMVC的工作原理主要基于请求驱动,它采用了前端控制器模式来进行设计。以下是SpringMVC工作原理的详细解释: 请求接收与分发: 当用户发送一个请求到Web服务器时,这个请求首先会被SpringMVC的前端控制器(Dispatche…

VUE识别图片文字OCR(tesseract.js)

效果:1&#xff1a; 效果图2&#xff1a; 一、安装tesseract.js npm i tesseract.js 二、静态页面实现 <template><div><div style"marginTop:100px"><input change"handleChage" type"file" id"image-input"…