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


    创作灵感

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

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

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

    第一种写法(错误示例)

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

    1. @Override
    2. public ApplyRecord[] getApplyRecords() {
    3. ApplyRecord[] applyRecords=applyRecordMapper.getApplyRecords();
    4. for (ApplyRecord applyRecord : applyRecords) {
    5. User user= userMapper.getAllById(applyRecord.getUserId());
    6. applyRecord.setName(user.getName());
    7. ActivityRecord[] activityRecords = new ActivityRecord[6];
    8. ActivityRecord activityRecordOne=activityRecordMapper.getActivityRecordById(
    9. applyRecord.getActivityRecordIdOne());//获取申请素拓记录中提交的六次活动记录
    10. ActivityRecord activityRecordTwo=activityRecordMapper.getActivityRecordById(
    11. applyRecord.getActivityRecordIdTwo());//获取申请素拓记录中提交的六次活动记录
    12. ActivityRecord activityRecordThree=activityRecordMapper.getActivityRecordById(
    13. applyRecord.getActivityRecordIdThree());//获取申请素拓记录中提交的六次活动记录
    14. ActivityRecord activityRecordFour=activityRecordMapper.getActivityRecordById(
    15. applyRecord.getActivityRecordIdFour());//获取申请素拓记录中提交的六次活动记录
    16. ActivityRecord activityRecordFive=activityRecordMapper.getActivityRecordById(
    17. applyRecord.getActivityRecordIdFive());//获取申请素拓记录中提交的六次活动记录
    18. ActivityRecord activityRecordSix=activityRecordMapper.getActivityRecordById(
    19. applyRecord.getActivityRecordIdSix());//获取申请素拓记录中提交的六次活动记录
    20. Activity activityOne=activityMapper.getAllById(activityRecordOne.getActivityId());
    21. activityRecordOne.setName(activityOne.getName());
    22. activityRecordOne.setDate(activityOne.getDate());
    23. Activity activityTwo=activityMapper.getAllById(activityRecordTwo.getActivityId());
    24. activityRecordTwo.setName(activityTwo.getName());
    25. activityRecordTwo.setDate(activityTwo.getDate());
    26. Activity activityThree=activityMapper.getAllById(activityRecordThree.getActivityId());
    27. activityRecordThree.setName(activityThree.getName());
    28. activityRecordThree.setDate(activityThree.getDate());
    29. Activity activityFour=activityMapper.getAllById(activityRecordFour.getActivityId());
    30. activityRecordFour.setName(activityFour.getName());
    31. activityRecordFour.setDate(activityFour.getDate());
    32. Activity activityFive=activityMapper.getAllById(activityRecordFive.getActivityId());
    33. activityRecordFive.setName(activityFive.getName());
    34. activityRecordFive.setDate(activityFive.getDate());
    35. Activity activitySix=activityMapper.getAllById(activityRecordSix.getActivityId());
    36. activityRecordSix.setName(activitySix.getName());
    37. activityRecordSix.setDate(activitySix.getDate());
    38. activityRecords[0]=activityRecordOne;
    39. activityRecords[1]=activityRecordTwo;
    40. activityRecords[2]=activityRecordThree;
    41. activityRecords[3]=activityRecordFour;
    42. activityRecords[4]=activityRecordFive;
    43. activityRecords[5]=activityRecordSix;
    44. applyRecord.setActivityRecords(activityRecords);
    45. }
    46. return applyRecords;
    47. }

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

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

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

    第二种写法(正确示例)

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

    1. @Select("SELECT * FROM applyRecord WHERE userId=#{userId} ORDER BY date DESC LIMIT #{start},10")
    2. @Results({
    3. @Result(column = "date",property = "date"),//申请时间
    4. @Result(column = "status",property = "status"),//申请状态
    5. @Result(
    6. column = "userId",
    7. property = "user",
    8. javaType= User.class,
    9. one = @One(select="org.example.Mapper.UserMapper.getAllById")
    10. ),
    11. @Result(
    12. column = "activityRecordIdOne,activityRecordIdOne,activityRecordIdTwo,activityRecordIdTwo," +
    13. "activityRecordIdThree,activityRecordIdThree,activityRecordIdFour,activityRecordIdFour," +
    14. "activityRecordIdFive,activityRecordIdFive,activityRecordIdSix,activityRecordIdSix",
    15. property = "activityRecords",
    16. javaType = ActivityRecord[].class,
    17. many = @Many(select = "org.example.Mapper.ActivityRecordMapper.getActivityRecordsInIds")
    18. )
    19. })
    20. ApplyRecord[] getApplyRecordsByUserId(@Param("userId") Integer userId,@Param("start") Integer start);

    ApplyRecordMapper文件

    1. @Select("SELECT * FROM (activityRecord,activity) WHERE activityRecord.id IN (#{activityRecordIdOne}," +
    2. "#{activityRecordIdTwo},#{activityRecordIdThree},#{activityRecordIdFour},#{activityRecordIdFive}," +
    3. "#{activityRecordIdSix}) AND activity.id=activityRecord.activityId")
    4. ActivityRecord[] getActivityRecordsInIds(@Param("activityRecordIdOne") Integer activityRecordIdOne,
    5. @Param("activityRecordIdTwo") Integer activityRecordIdTwo,
    6. @Param("activityRecordIdThree") Integer activityRecordIdThree,
    7. @Param("activityRecordIdFour") Integer activityRecordIdFour,
    8. @Param("activityRecordIdFive") Integer activityRecordIdFive,
    9. @Param("activityRecordIdSix") Integer activityRecordIdSix);

    ActivityRecordMapper文件

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

    难点解释

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

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

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

  • 相关阅读:
    san.js源码解读之模版解析(parseTemplate)篇——readIdent函数
    HNU计网实验:实验一 应用协议与数据包分析实验(使用Wireshark)
    Java开发树结构数据封装!
    Go简单实现协程池
    SAE J3016路面机动车驾驶自动化系统相关术语的分类和定义(2021中文版-全文)
    Java学习随便记2
    【Linux】进程_7
    Docker 镜像库国内加速的几种方法
    论文解读《Cauchy Graph Embedding》
    【漏洞复现】通达oa 前台sql注入
  • 原文地址:https://blog.csdn.net/m0_60689237/article/details/138025423