蔡昊 - 如何高效而优雅的进行对象转换

简介: 简介随着分层结构和DDD设计思想的普及,我们在后端开发过程中,会使用到VO/DO/DTO等等各种类型的模型对象,对象的转换工作也随着变得越来越多。而这种工作技术含量不高,却容易过多的出现在编码里,处理不当也会出现各种问题,那么如何更加高效而优雅的进行类型转换呢?且花几分钟了解下笔者接下来要讲的一款Java代码生成器MapStruct——创建实现Java Bean之间转换的扩展映射器!

MapStruct的优点

首先,我们了解下常见的转换对象方法:

// 1. getter+setter 这种方式会产生大量无意义工作和重复代码
// 2. BeanUtils      
这种方式适用处理简单结构的转换,遇到字段名称不对应等情况,仍需要额外的处理
BeanUtils.copyProperties(Object source,Object target)

MapStruct特点

•            简单、自动化

•            编译时生成映射,确保运行时性能

•            只需要创建接口,大大减少样板代码的编码工作

MapStruct的使用

1. 引包与配置

<properties>                
   <org.mapstruct.version>1.4.1.Final</org.mapstruct.version>
</properties>

<dependency>
   <groupId>org.mapstruct</groupId>
   <artifactId>mapstruct</artifactId>
   <version>${org.mapstruct.version}</version>
</dependency>
<dependency>
   <groupId>org.mapstruct</groupId>
   <artifactId>mapstruct-processor</artifactId>
   <version>${org.mapstruct.version}</version>
</dependency>

*最新maven版本:https://mvnrepository.com/artifact/org.mapstruct/mapstruct

2. 编码及基本使用

先看下需要转换的两个类,这里简化模型,仅仅以VODO做为案例:

@Data
publicclass UserVO{
   privateLong id;
   privateString userName;
   privateString email;
   privateInteger gender;
}

@Data
@TableName(value ="User")
publicclass User implementsSerializable{
   privatestaticfinallong serialVersionUID =1L;

   @TableId(type = IdType.AUTO)
   privateLong id;
   privateString name;
   privateString email;
   privateString createdDate;
   privateString updatedDate;
   privateInteger gender;
}

第一步:下面是新建一个转换类的接口:

/**
* UserTransfer
*
* @author CaiHao
*@since 2022/3/1011:42
*/
//
标记为映射接口,@Mapper允许接口mapstruct-processor在编译期启动
@Mapper
publicinterface UserTransfer {

   UserTransfer INSTANCE = Mappers.getMapper(UserTransfer.class);

   //
映射名称不同的字段
   @Mapping(source ="userName", target ="name")
   //
声明转换方法
   User toDo(UserVO vo);

   @Mapping(source ="name", target ="userName")
   UserVO toVo(User user);

   // list
转换
   List<User>toDo(List<UserVO> voList);

   List<UserVO>toVo(List<User> doList);
}

第二步:如何使用

// 方式一:通过INSTANCE实现访问
User user = UserTransfer.INSTANCE.toDo(tom);

或使用@Mapper(componentModel = "spring")

// 方式二:注入UserTransfer userTransfer;
User user = userTransfer.toDo(tom);

3. 拓展应用

情况一:变量为实体(嵌套bean

@Data
@Builder
@AllArgsConstructor
publicclass EmployeeVO {
   privateLong id;
   privateString empName;
   privateString gender;

   private Contact contact;
}

@Data
publicclass Contact {
   privateString address;
   privateString phone;
   privateString email;
}

@Data
@Builder
publicclass UserVO {
   privateLong id;
   privateString userName;
   privateString email;
   privateInteger gender;
   privateString address;
   privateString phone;
}

@Mapper
publicinterface UserTransfer {
   UserTransfer INSTANCE = Mappers.getMapper(UserTransfer.class);
   /**
    * UserVO
转换成EmployeeVO
    *
    * @param userVO userVO
    *@return EmployeeVO EmployeeVO
    */
   @Mapping(source ="userName", target ="empName")
   @Mapping(source ="email", target ="contact.email")
   @Mapping(source ="address", target ="contact.address")
   @Mapping(source ="phone", target ="contact.phone")
   EmployeeVO toEmployeeVO(UserVO userVO);
}

EmployeeVO employeeVO = UserTransfer.INSTANCE.toEmployeeVO(tom);

情况二: 类型转换、映射合成

publicclass User{    
   privateString updatedDate;
   privateInteger gender;
}

publicclass UserVO {
   privateDate gmtCreate;
   privateString gender;
}

@Mappings({
@Mapping(target ="gender", expression="java(java.lang.String.valueOf(user.getGender()))"),
@Mapping(source ="createdDate", target ="gmtCreate", dateFormat ="yyyy-MM-dd HH:mm")
})
UserVO toVo(User user);

mapstruct的应用场景广泛,如转换、处理第三方服务结果集,同时配合Lombok注解,可以发挥出更好的效果。

*关于更多高级属性和方法,可以查看官方文档

相关文章
|
机器学习/深度学习 并行计算 PyTorch
CUDA驱动深度学习发展 - 技术全解与实战
CUDA驱动深度学习发展 - 技术全解与实战
871 1
|
Web App开发 Cloud Native Docker
删除容器报错:Error response from daemon: conflict: unable to delete
云原生日益普及的现在,docker容器化成为现有很多服务的改进方向,docker凭借更高效的利用系统资源、更快速的启动时间、一致的运行环境、持续支付和部署、更轻松的迁移、更轻松的维护和拓展等优势,迅速走红。但是,很多容器部署后在回收时,都会遇到各种各样的问题,比如今天讨论的删除镜像的问题,有时候删除操作会莫名其妙的报错。
1340 1
|
11月前
|
安全 数据处理 Python
Python 函数式编程:让代码更简洁高效
Python 函数式编程:让代码更简洁高效
539 107
|
Arthas 监控 Java
Arthas logger(查看 logger 信息,更新 logger level)
Arthas logger(查看 logger 信息,更新 logger level)
493 6
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
Vue2滑动输入条(Slider)
这是一个基于 Vue3 的滑动输入条(Slider)组件,提供了丰富的自定义选项,如最小值、最大值、初始值、宽度、禁用状态及双滑块模式等。用户可通过拖动滑块或点击输入条调整数值。代码示例展示了如何创建组件及在页面中引入使用。包含单滑块与双滑块模式的效果图。
681 2
Vue2滑动输入条(Slider)
|
存储 算法 C语言
数据结构基础详解(C语言): 二叉树的遍历_线索二叉树_树的存储结构_树与森林详解
本文从二叉树遍历入手,详细介绍了先序、中序和后序遍历方法,并探讨了如何构建二叉树及线索二叉树的概念。接着,文章讲解了树和森林的存储结构,特别是如何将树与森林转换为二叉树形式,以便利用二叉树的遍历方法。最后,讨论了树和森林的遍历算法,包括先根、后根和层次遍历。通过这些内容,读者可以全面了解二叉树及其相关概念。
592 6
|
数据采集 数据可视化 大数据
R语言在统计分析中的应用与实践
【7月更文挑战第30天】R语言以其强大的统计分析能力和开源自由的特性,在统计分析领域发挥着重要作用。无论是基础的描述性统计、推断性统计,还是复杂的回归分析、时间序列分析和生存分析,R语言都提供了丰富的函数和包来支持。通过学习和掌握R语言,数据分析师和研究者可以更加高效地进行数据分析,获取有价值的信息和结论。未来,随着大数据和云计算等新兴技术的发展,R语言的应用前景将更加广阔。
|
存储 传感器 算法
Hello World CGAL 5.4入门
Hello World CGAL 5.4入门
425 3
|
网络协议 安全 API
计算机网络——基本概念(计算机网络,Internet,网络协议)
计算机网络——基本概念(计算机网络,Internet,网络协议)
1880 2