技术分享
🔃VO对象转换与数据翻译
00 分钟
2024-7-28
2024-7-29
type
status
date
Jul 29, 2024 02:10 AM
slug
summary
category
tags
password
icon
说明:这里的 VO 是泛指 Java POJO 对象,也可以是 DTO、BO 等等。

对象转换

背景

为了让应用的代码更易维护,我们往往会将项目进行分层。在《阿里巴巴 Java 开发手册》中,推荐分层如下图:
notion image
分层之后,每一层都有自己的领域模型,即不同类型的 Bean:
  • DO(Data Object):与数据库表结构一一对应,通过DAO层向上传输数据源对象。
  • DTO(Data Transfer Object):数据传输对象,Service或Manager向外传输的对象。
  • BO(Business Object):业务对象。由Service层输出的封装业务逻辑的对象。
  • 等等...
那么就需要对象转换,顾名思义,独享转换指的是 A 类型对象,转换成 B 类型对象。例如说,我们有一个 UserDO 类型对象,需要转换成 UserVO 或者 UserDTO 类型对象。
市面上有很多的对象转换工具,例如说 MapStruct、Dozer、各种 BeanUtils、BeanCopier 等等(Performance of Java Mapping Frameworks)。个人最喜欢MapStruct。
相比来说,MapStruct 性能会略好于 BeanUtils,但是相比数据库操作带来的耗时来说,基本可以忽略不计。因此,一般情况下,建议使用 BeanUtils 即可。

MapStruct简介

官网:
MapStruct 是用于生成类型安全的 Bean 映射类的 Java 注解处理器。
你所要做的就是定义一个映射器接口,声明任何需要映射的方法。在编译过程中,MapStruct 将生成该接口的实现。此实现使用纯 Java 的方法调用源对象和目标对象之间进行映射,并非 Java 反射机制
与手工编写映射代码相比,MapStruct 通过生成冗长且容易出错的代码来节省时间。在配置方法的约定之后,MapStruct 使用了合理的默认值,但在配置或实现特殊行为时将不再适用。
与动态映射框架相比,MapStruct 具有以下优点:
  • 使用纯 Java 方法代替 Java 反射机制快速执行。
  • 编译时类型安全:只能映射彼此的对象和属性,不能映射一个 Order 实体到一个 Customer DTO 中等等。
  • 如果无法映射实体或属性,则在编译时清除错误报告。

MapStruct简单使用

引入Maven依赖

💡
注意:lombok的依赖放在mapstruct 上面,否则会出现转换的对象为 null 的情况。

定义转换对象

假设这里有两个类:UserVOUserDTO,其定义如下。现在需要把UserVO转换为UserDTO

UserConvert

  1. 通过添加 @Mapper 注解,声明它是一个 MapStruct Mapper 映射器。
  1. 通过调用 Mappers 的 #getMapper(Class<T> clazz) 方法,获得 MapStruct 帮我们自动生成的 UserConvert 实现类的对象。
  1. 定义 #convert(UserVO userDO) 方法,声明 UserVO 转换成 UserDO
编译生成的UserConvertImpl如下:

测试

输出如下:

MapStruct属性忽略

当转换的两个对象都有特殊的字段时,直接使用上面的转换方法#convert会出现错误:Unmapped target property: "propertyName",此时可以使用ignore属性设置转换的过程中忽略哪些字段。

定义转换对象

  • UserVO有自己独有的字段email
  • UserDO有自己独有的字段address

UserConvert

  1. UserVO转换为UserDO时,设置注解的target属性为 UserDO 的 address 属性,并将其忽略。
  1. UserDO转换为UserVO时,设置注解的target属性为 UserVO 的 email属性,并将其忽略。

UserConvertImpl

可以看到,当UserVO转换为UserDO时,忽略了UserDO 的 address 属性。当UserDO转换为UserVO时,忽略了 UserVO 的 email属性。

测试

可以看到,在转换的时候UserVO对象设置了email属性,但是不影响,最终结果输出如下:

MapStruct属性转换

UserVO的属性为id,而UserDO的属性为userId时,可以同时设置转换的sourcetraget属性。

定义转换对象

UserConvert

  • @Mappings中可以定义多个@Mapping

UserConvertImpl

可以看到UserDO中的userId字段值是 UserVOid

测试

输入结果如下:

数据翻译

// TODO:Building
 

评论
Loading...