type
status
date
Jul 29, 2024 02:10 AM
slug
summary
category
tags
password
icon
对象转换背景MapStruct简介MapStruct简单使用引入Maven依赖定义转换对象UserConvert测试MapStruct属性忽略定义转换对象UserConvertUserConvertImpl测试MapStruct属性转换定义转换对象UserConvertUserConvertImpl测试数据翻译
说明:这里的 VO 是泛指 Java POJO 对象,也可以是 DTO、BO 等等。
对象转换
背景
为了让应用的代码更易维护,我们往往会将项目进行分层。在《阿里巴巴 Java 开发手册》中,推荐分层如下图:
分层之后,每一层都有自己的领域模型,即不同类型的 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
的情况。定义转换对象
假设这里有两个类:
UserVO
和UserDTO
,其定义如下。现在需要把UserVO
转换为UserDTO
。UserConvert
- 通过添加
@Mapper
注解,声明它是一个 MapStruct Mapper 映射器。
- 通过调用 Mappers 的
#getMapper(Class<T> clazz)
方法,获得 MapStruct 帮我们自动生成的 UserConvert 实现类的对象。
- 定义
#convert(UserVO userDO)
方法,声明UserVO
转换成UserDO
。
编译生成的UserConvertImpl如下:
测试
输出如下:
MapStruct属性忽略
当转换的两个对象都有特殊的字段时,直接使用上面的转换方法
#convert
会出现错误:Unmapped target property: "propertyName",此时可以使用ignore
属性设置转换的过程中忽略哪些字段。定义转换对象
UserVO
有自己独有的字段email
。
UserDO
有自己独有的字段address
。
UserConvert
- 当
UserVO
转换为UserDO
时,设置注解的target
属性为UserDO
的address
属性,并将其忽略。
- 当
UserDO
转换为UserVO
时,设置注解的target
属性为UserVO
的email
属性,并将其忽略。
UserConvertImpl
可以看到,当
UserVO
转换为UserDO
时,忽略了UserDO
的 address
属性。当UserDO
转换为UserVO
时,忽略了 UserVO
的 email
属性。测试
可以看到,在转换的时候
UserVO
对象设置了email
属性,但是不影响,最终结果输出如下:MapStruct属性转换
当
UserVO
的属性为id
,而UserDO
的属性为userId
时,可以同时设置转换的source
和traget
属性。定义转换对象
UserConvert
@Mappings
中可以定义多个@Mapping
UserConvertImpl
可以看到
UserDO
中的userId
字段值是 UserVO
的id
。测试
输入结果如下:
数据翻译
// TODO:Building
- 作者:Frank
- 链接:https://blog.franksteven.me//article/obj_map_trans
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。