带你多种方法实体类转换 玩转VO,PO,DTO 之间转换
前置篇
首先介绍一下这些VO PO DTO 等等这些的概念。方便我们的理解。
首先我们来说用的比较多的,就是DTO 和 VO
随着互联网的发展,前后端分离的开发模式越来越流行。在前后端数据交互过程中,为了保证数据的安全性和效率,通常会采用 DTO 和 VO 来封装数据。
DTO(Data Transfer Object)和 VO(Value Object)都是一种设计模式,用于封装数据和提供服务。
这里需要注意的是这个VO
我看有的地方也这样写:VO(
View Object
):视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。这个问题,我在查询了很多资料后,得到了这样的解释:
尽管 “View Object” 也是一个有效的解释,但在面向对象设计和领域驱动设计(DDD)的上下文中,VO 通常指的是 “Value Object”。选择哪种解释取决于具体的上下文和使用场景。
- 当讨论数据结构和业务逻辑时,VO 很可能指的是 “Value Object”。
- 当讨论用户界面和MVC架构时,VO 可能指的是 “View Object”。
因此,我们最好是根据该上下文来判断它指的是 “Value Object” 还是 “View Object”。
它们的主要区别在于:
- DTO:用于封装数据传输对象,可以将数据库中的数据转换为前端需要的格式,方便前后端之间的数据交互。
- VO:用于封装值对象,可以根据具体的需求来封装不同的数据属性,方便前端页面的显示和交互。
DTO 是一种数据传输对象,用于将数据库中的数据转换为前端需要的格式,方便前后端之间的数据交互。而 VO 是一种值对象,用于封装不同的数据属性,方便前端页面的显示和交互。
这俩个也是非常容易搞混的。
可以这样说,对于绝大部分的应用场景来说,DTO和VO的属性值基本是一致的,而且他们通常都是POJO,那么既然有了VO,为什么还需要DTO呢?
比较常见的操作,就是用户的数据脱敏。
当然,在有些项目中,我见到DTO的命名规范是xxxrequest
Vo的命名规范是xxxresponse
这个只是一个命名规范。
之后我们来了解什么是PO和DAO
PO(Persistent Object) 通常指的是与数据库中的表相映射的Java对象。它包含与数据库表字段相对应的私有成员变量以及相应的get和set方法,用于封装数据库表中的一条记录。PO类通常用于数据访问层(DAO层),作为数据库与应用程序之间的桥梁,实现数据的持久化存储和检索。
为了防止很多人跟这个领域对象弄混。
接下来我说一下这个阿里对于领域对象的一个规范:
1) 数据对象:xxxDO,xxx 即为数据表名。 2) 数据传输对象:xxxDTO,xxx 为业务领域相关的名称。 3) 展示对象:xxxVO,xxx 一般为网页名称。 4) POJO 是 DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO。
这里的DO 就相当于是PO 是没有什么区别的,或者说是很少的。
下面我将用一个图和案例来带你首先了解这些东西。
之后我们在通过程序来描述一下这几个的区别
首先我们来看一下数据库表:
1 | sql复制代码user_id bigint not null comment '用户id' |
这个是所有的字段。
之后我们先来看最简单的po层,也就是和这个数据库是一一对应的。
1 | kotlin复制代码@Data |
之后我们用用户登陆这个案例来演示VO和DTO
VO假设我们只想返回前端一个username
那么我们的属性就只有一个username
1 | java复制代码@Data |
之后来看DTO
1 | kotlin复制代码@Data |
在dto这里我们可以使用一些校验框架来限制。这个就是前端页面或者是服务调用方传给我们的参数。也就是账号和密码来完成登陆。
之后我们开始来进行转换吧。
实战篇
Beanutils
这个是比较简单的一个方法。也是我经常在用的方式
下面是一个示例:
1 | java复制代码import org.springframework.beans.BeanUtils; |
这里需要注意的是。
import org.springframework.beans.BeanUtils;
我用的是这个Beanutils
如果你用的是import org.apache.commons.beanutils.BeanUtils;
这个的话,那么这俩个方法的copyProperties 的源和目标的参数的位置是相反的。
这个可以说是很简单的,如果你需要添加注释,我这里推荐一个插件是BeanUtilsHelper
他可以支持将beanutils的这个代码转换为最原始的set get到的值的方法。有兴趣的可以去试试,还可以支持很多的注解。
之后要说的是一个性能爆炸,高级优雅,大厂标准的转换方法
MapStcurt
如果要使用 MapStruct 库进行对象之间的映射,首先需要定义一个 Mapper 接口,并在接口中编写映射方法。然后,MapStruct 库会自动生成对应的映射实现类。
首先,在 pom.xml
文件中添加 MapStruct 的依赖:
1 | xml复制代码xmlCopy code<dependency> |
然后,定义一个 Mapper 接口:
1 | ini复制代码import org.mapstruct.Mapper; |
下面看一个他在spring中的应用:
1 | kotlin复制代码package com.xiaou.pan.server.modules.user.converter; |
除了这个之外,@mapping还有很多的参数,
比如说expression
1 | ini复制代码@Mapping(target = "userId", expression = "java(com.xiaou.pan.server.common.utils.UserIdUtil.get())") |
这个就是可以执行一个java代码。
他实际上的原理就是为我们自动书写实现类:
ModelMapper
1 | java复制代码import org.modelmapper.ModelMapper; |
使用 ModelMapper 可以更加灵活地定义属性映射规则,只需创建一个 ModelMapper 对象,然后调用其 map
方法即可实现对象之间的属性拷贝。
后记
最后呢,我想说,这些什么VO PO DTO 包括有什么 BO SO 什么的,如果你开发的大型项目。是需要进行一个完整的架构的,但是我们如果是一些小项目,没有必要为了设计而设计,导致的过度设计。
本文转载自: 掘金