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

server/2024/9/23 3:22:48/

创作灵感

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

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

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

第一种写法(错误示例)

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

@Overridepublic 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方法传递参数一样,时以键值对的方式进行传递的。只不过我的键与值都是同样的名字而已。

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

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


http://www.ppmy.cn/server/13961.html

相关文章

C++多态(个人笔记)

C多态 1.多态的定义以及实现1.1多态的构成条件1.2虚函数1.3虚函数的重写1.4override和final1.5函数重载,覆盖(重写),隐藏(重定义)区别 2.抽象类2.1接口继承和实现继承的区别 3.多态原理3.1虚函数表3.2多态的…

人工智能(AI)与地理信息技术(GIS)的融合:开启智能地理信息时代

随着科技的不断发展,人工智能(AI)和地理信息技术(GIS)的应用越来越广泛,两者的结合更是为许多行业带来了前所未有的变革。本文将以“人工智能(AI)地理信息技术(GIS&#…

C++左值引用与右值引用

首先,我们需要知道什么是值语义,什么是引用语义。 值语义: 值语义意味着对象在被传递、赋值或拷贝时,会复制其整个数据。当使用值语义时,对对象进行操作不会影响原始对象,因为操作会在副本上进行。传统的…

力扣面试 150二叉搜索树迭代器 中序遍历 栈模拟递归 步骤拆分

Problem: 173. 二叉搜索树迭代器 思路 &#x1f469;‍&#x1f3eb; 三叶 复杂度 时间复杂度: O ( 1 ) O(1) O(1) 空间复杂度: O ( h ) O(h) O(h) Code class BSTIterator { Stack<TreeNode> d new Stack<>();public BSTIterator(TreeNode root){dfsLe…

深入解析YOLOv2

深入解析YOLOv2 引言 目标检测是计算机视觉中的一个核心问题&#xff0c;它旨在识别图像中所有感兴趣的目标&#xff0c;并给出它们的类别和位置。近年来&#xff0c;随着深度学习技术的发展&#xff0c;目标检测领域取得了巨大的进步。YOLO&#xff08;You Only Look Once&a…

vue 瀑布流布局 复制即用

插件 npm install vue-waterfall-plugin-next 或者 yarn add vue-waterfall-plugin-next 点击vue-waterfall-plugin-next进入文档 组件 <template><Waterfall :lazyload"false" :breakpoints"breakpoints" :gutter"8" :list"…

【零基础入门TypeScript】环境

目录 定义环境 句法 例子 环境声明是告诉 TypeScript 编译器实际源代码存在于其他地方的一种方式。当您使用大量第三方js库&#xff08;如 jquery/angularjs/nodejs&#xff09;时&#xff0c;您无法在 TypeScript 中重写它。对于 TypeScript 程序员来说&#xff0c;在使用这…

中国航天日特辑 | PARASOFT——从NASA JPL到航空航天的星辰大海

4月24日&#xff0c;是中国航天日&#xff08;Space Day of China&#xff09;&#xff0c;一个庆祝和纪念中国航天事业成就的特殊时刻。在这一天&#xff0c;我们不仅仅是赞颂那些辉煌的航天成就&#xff0c;还要探讨那些为航天事业做出重大贡献的合作伙伴和技术解决方案提供者…