写在前面:本文更多的讲解的是VO对比Map的用法,而非概念.

对VO、PO甚至是DO、DTO不熟悉的小伙伴请自行百度。



文章目录

  • ​​一、希望达到的效果​​
  • ​​二、方式一:使用VO​​
  • ​​三、方式二:使用Map​​
  • ​​四、对比分析​​




一、希望达到的效果



前端的显示效果:

这里的数据,分别来自两张表。账号名称来自T_ADMIN表,VO数据测试列来自VO_TEST表

VO与Map之间的相互转换_字段



数据库的数据:


VO与Map之间的相互转换_数据_02

VO与Map之间的相互转换_字段_03


我们要做的就是将两张表进行关联,然后获取我们需要的数据,然后展示在前端



这是在项目中是十分常见的情况,如果你没有见到,如果你觉得不常见,那么加油,你要走的路还长。



这里我将两种常见的方式进行一个归纳总结,希望对你有帮助。



二、方式一:使用VO

只截取部分重要代码



1、实体类代码,用来和我们前端显示的字段相对应

为返回给前端的显示数据新建实体类(成员变量名来自两张不同表的字段)


VO与Map之间的相互转换_数据_04



2、查询语句接口及对应的mapper.xml(重点)代码

我们在编写resultMap时中,一定要注意匹配对应字段的类型

VO与Map之间的相互转换_实体类_05


VO与Map之间的相互转换_字段_06


3、service层代码

该层的附属操作为使用分页插件进行分页,查询的代码为第二行


VO与Map之间的相互转换_数据_07


4、controller层代码

将我们查询到的数据封装到modelMap对象中,然后返回给前端


VO与Map之间的相互转换_实体类_08


5、前端JS代码

获取请求域中的list,然后取一个别名为adminVo,再使用adminVo分别去访问对应的属性值


VO与Map之间的相互转换_数据_09


这个操作总结下来就是:如果前端展示的数据无法来自一个已有的PO。那么我们就新建一个VO,并且将查询到的数据封装到VO实体类(我们这里是AdminVo)中,再将实体类放到我们的List集合中。然后辅以分页插件的分页操作(添加对应的分页数据,让前端能够进行分页处理),将数据放入到modelMap对象中,传到前端。最后前端对数据进行遍历,并按照指定格式显示数据。

总结一句话:后端封装好数据,前端遍历数据



既然前端只是遍历展示数据,那么我们数据的组成关键就在于后端封装好的数据是什么样子。


5、断点打在controller层方法的最后一行,调试代码观察数据

我们不难发现,传给前端的数据也就这几个

我们查询出来的数据被封装在pageInfo下的list集合中,以对象的形式进行存储

VO与Map之间的相互转换_实体类_10


VO与Map之间的相互转换_数据_11


关键数据的形式:我们可以理解为将属性-数据键值对封装在一个AdminVo实体类中,然后再将实体类放到我们的List集合中。这里的属性-数据键值对,让我很容易就想到了map中的key-value,如果我们将Admin替换为map,再将map放到我们的List集合中,效果是不是一样呢?

补充一句:那几种集合(ArrayList、LinkedList、HashSet、HashMap这四个最最最基本的集合特性一定要烂熟于心)在项目中十分常见,面试中也是重点。


其实是一样的。接下来我就演示给你看。



三、方式二:使用Map



1、接口及mapper.xml(重点)代码

此次没有VO实体类,直接使用一个HashMap来处理,


VO与Map之间的相互转换_字段_12


VO与Map之间的相互转换_数据_13


2、service层代码


VO与Map之间的相互转换_实体类_14


3、contoller层代码不变


4、前端JS代码

由于没有了实体类,所以我们遍历数据时,遍历的字段要和Mapper.xml中SQL语句执行后的字段进行匹配


VO与Map之间的相互转换_实体类_15


5、同样的位置进行断点调试

我们查询出来的数据被封装在pageInfo下的list集合中,以HashMap的形式进行存储


VO与Map之间的相互转换_字段_16


VO与Map之间的相互转换_数据_17


为了更加直观的观察到两者的区别,我将它们的不同点再放一次

VO对应的是实体类AdminVo

Map对应的是集合HashMap


VO与Map之间的相互转换_数据_18


VO与Map之间的相互转换_实体类_19



四、对比分析



使用VO

优点:

  1. 当我们新建一个VO实体类时,能够更加方便的观察到传输数据的属性有哪些,继而能更更加方便的添加或者扩展操作,有利于项目的后期维护
  2. 能够本质上避免多个表中的相同字段,而不是通过取别名的方式
  3. 通过resultMap的配置,能够降低SQL和映射关系之间的耦合性
  4. 数据的传输过程更好理解

缺点:

  1. 每出现一个新的业务需求,就需要新建一个VO,使得代码过于冗余
  2. 比Map多新建VO实体类,并且配置对应的映射关系,增加代码量
  3. 当实体类成员变量发生增加或修改时,需要同时修改对应的映射关系,十分不方便


使用Map

优点:

  1. 不需要新建VO实体类,也不需要配置对应的映射关系,所有字段全部放在map集合中即可
  2. Map获取字段或修改字段时更加灵活方便,耦合度更低
  3. Map中可以封装更多的参数,继而让功能更加丰富。如添加自己实现分页所需的参数、添加相关参数用于和动态SQL一起条件查询。

缺点:

  1. 过多的使用Map封装参数,会让后来的拿到项目的人看得一脸懵逼,因为无法了解到Map中到底是什么
  2. 不利于代码排错,错误只会出现在最终的mapper.xml文件中,无法方便的定位错误来源
  3. 在前后端分离的项目中,Swagger无法识别Map集合中的参数类型
  4. 无法在实体类层面,对即将传入的参数进行数据校验


最佳实践

  1. 如果是小型项目,想偷懒那就使用map,毕竟变量个数和代码体量都在一个可控的范围内
  2. 团队开发中,如果参数比较多,那就使用VO;如果参数较少,可以使用map,并且添加对应的map注释即可。把代码写好,就是造福一方。
  3. 根据公司的代码规范,公司是老大,他怎么制定的规范就怎么来


以上观点,纯属个人见解,如有不正确之处,欢迎指出。共同进步!!!