当前位置:网站首页>After encountering MapStruct, the conversion between PO, DTO and VO objects is no longer handwritten
After encountering MapStruct, the conversion between PO, DTO and VO objects is no longer handwritten
2022-08-04 20:25:00 【51CTO】
介绍
在工作中,我们经常要进行各种对象之间的转换.
PO:persistent object 持久对象,对应数据库中的一条记录
VO:view object 表现层对象,最终返回给前端的对象
DTO:data transfer object数据传输对象,如dubbo服务之间传输的对象
如果这些对象的属性名相同还好,可以用如下工具类赋值
Spring BeanUtils
Cglib BeanCopier
避免使用Apache BeanUtils,性能较差
如果属性名不同呢?如果是将多个PO对象合并成一个VO对象呢?好在有MapStruct神器,可以帮助我们快速转换
在pom文件中加入如下依赖即可
< dependency >
< groupId >org.mapstruct </ groupId >
< artifactId >mapstruct-jdk8 </ artifactId >
< version >1.2.0.CR1 </ version >
</ dependency >
< dependency >
< groupId >org.mapstruct </ groupId >
< artifactId >mapstruct-processor </ artifactId >
< version >1.2.0.CR1 </ version >
< scope >provided </ scope >
</ dependency >
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
对象互转
@Mapper
public interface StudentMapper {
StudentMapper INSTANCE = Mappers. getMapper( StudentMapper. class);
@Mappings({
@Mapping( source = "name", target = "studentName"),
@Mapping( source = "age", target = "studentAge")
})
StudentVO po2Vo( StudentPO studentPO);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 新建一个Mapper接口,上面加上@Mapper注解
- 新建一个成员变量INSTANCE
- 用@Mapping注解指定映射关系,名字相同的就不用再指定了,会自动映射
测试效果如下,名字不同且没有指定映射关系的会被设置为null
@Test
public void studentPo2Vo() {
StudentPO studentPO = StudentPO. builder(). id( 10). name( "test")
. age( 24). className( "教室名"). build();
StudentVO studentVO = StudentMapper. INSTANCE. po2Vo( studentPO);
// StudentVO(id=10, studentName=test, studentAge=24, schoolName=null)
System. out. println( studentVO);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
List互转
@Mapper
public interface StudentMapper {
StudentMapper INSTANCE = Mappers. getMapper( StudentMapper. class);
@Mappings({
@Mapping( source = "name", target = "studentName"),
@Mapping( source = "age", target = "studentAge")
})
StudentVO po2Vo( StudentPO studentPO);
List < StudentVO > poList2VoList( List < StudentPO > studentPO);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
List类型互转的映射规则会用单个对象的映射规则,看测试效果
@Test
public void poList2VoList() {
List < StudentPO > studentPOList = new ArrayList <>();
for ( int i = 1; i <= 2; i ++) {
StudentPO studentPO = StudentPO. builder(). id( i). name( String. valueOf( i)). age( i). build();
studentPOList. add( studentPO);
}
List < StudentVO > studentVOList = StudentMapper. INSTANCE. poList2VoList( studentPOList);
// [StudentVO(id=1, studentName=1, studentAge=1, schoolName=null),
// StudentVO(id=2, studentName=2, studentAge=2, schoolName=null)]
System. out. println( studentVOList);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
多个对象映射一个对象
我们用SchoolPO和StudentPO来映射SchoolStudentVO
测试例子如下
@Test
public void mergeVo() {
SchoolPO schoolPO = SchoolPO. builder(). name( "学校名字"). build();
StudentPO studentPO = StudentPO. builder(). name( "学生名字"). build();
SchoolStudentVO schoolStudentVO = StudentMapper. INSTANCE. mergeVo( schoolPO, studentPO);
// SchoolStudentVO(schoolName=学校名字, studentName=学生名字)
System. out. println( schoolStudentVO);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
当然还有其他的骚操作,这里就简单介绍一个比较实用的技巧,有兴趣的可以看官方的example
https://github.com/mapstruct/mapstruct-examples
Specify the method when converting
当我们想把PersonVO转换为PersonPO,PersonPO中的gender是一个枚举,PersonVO中的gender是一个int类型,How to convert enum to enumvalue值呢?
在@Mapping注解中通过qualifiedByNameThe attribute specifies the method of conversion
@Mapper
public interface StudentMapper {
StudentMapper INSTANCE = Mappers. getMapper( StudentMapper. class);
@Mappings({
@Mapping( source = "gender", target = "gender", qualifiedByName = "convertGender"),
})
PersonPO vo2Po( PersonVO personVO);
@Named( "convertGender")
default Integer convertTargetType( GenderEnum genderEnum) {
return genderEnum. getValue();
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
测试类如下
实现原理
MapStruct帮你对接口生成了一个实现类,下面就是生成的实现类,从class文件夹中可以看到
public class StudentMapperImpl implements StudentMapper {
@Override
public StudentVO po2Vo( StudentPO studentPO) {
if ( studentPO == null ) {
return null;
}
StudentVO studentVO = new StudentVO();
studentVO. setStudentAge( studentPO. getAge() );
studentVO. setStudentName( studentPO. getName() );
studentVO. setId( studentPO. getId() );
return studentVO;
}
@Override
public List < StudentVO > poList2VoList( List < StudentPO > studentPO) {
if ( studentPO == null ) {
return null;
}
List < StudentVO > list = new ArrayList < StudentVO >( studentPO. size() );
for ( StudentPO studentPO1 : studentPO ) {
list. add( po2Vo( studentPO1 ) );
}
return list;
}
@Override
public SchoolStudentVO mergeVo( SchoolPO schoolPO, StudentPO studentPO) {
if ( schoolPO == null && studentPO == null ) {
return null;
}
SchoolStudentVO schoolStudentVO = new SchoolStudentVO();
if ( schoolPO != null ) {
schoolStudentVO. setSchoolName( schoolPO. getName() );
}
if ( studentPO != null ) {
schoolStudentVO. setStudentName( studentPO. getName() );
}
return schoolStudentVO;
}
@Override
public PersonPO vo2Po( PersonVO personVO) {
if ( personVO == null ) {
return null;
}
PersonPO personPO = new PersonPO();
personPO. setGender( convertTargetType( personVO. getGender() ) );
personPO. setAge( personVO. getAge() );
return personPO;
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
欢迎关注
参考博客
[0]http://www.tianshouzhi.com/api/tutorials/mapstruct
[1]https://www.jianshu.com/p/3f20ca1a93b0
边栏推荐
- 动态规划_双数组字符串
- 小软件大作用 | 如何省时省力进行Gerber图层快速对比?
- 如何手动下载并安装 Visual Studio Code 的 SAP Fiori tools - Extension Pack
- 刷题-洛谷-P1200 你的飞碟在这儿Your Ride Is Here
- 用“绿色计算“技术推动算力可持续发展
- 【有奖征文】秋招特训,打造你的专属产品体验
- 刷题-洛谷-P1317 低洼地
- Tear down the underlying mechanism of the five JOINs of SparkSQL
- Win10 uwp use ScaleTransform magnify an element
- SAP 电商云 Accelerator 和 Spartacus UI 的工作机制差异
猜你喜欢
Tear down the underlying mechanism of the five JOINs of SparkSQL
AWS SES 的监控和告警
小软件大作用 | 如何省时省力进行Gerber图层快速对比?
腾讯云胡启明:Kubernetes云上资源的分析与优化
vscode离线安装插件方法
How to promote the implementation of rural revitalization
【AGC】构建服务1-云函数示例
长时间序列遥感数据处理及在全球变化、物候提取、植被变绿与固碳分析、生物量估算与趋势分析等领域中的应用
【Web漏洞探索】跨站脚本漏洞
【学术相关】清华教授发文劝退读博:我见过太多博士生精神崩溃、心态失衡、身体垮掉、一事无成!...
随机推荐
linkboy 5.0 正式发布,新增语音识别、图像识别
构建Buildroot根文件系统(I.MX6ULL)
手撕SparkSQL五大JOIN的底层机制
二叉树的前序遍历
Qt Designer生成的图形可以自适应窗口的大小变化
零知识证明——zkSNARK证明体系
DICOM医学影像协议
泰山OFFICE技术讲座:底纹、高亮、边框的关系
The book "The Essence of Alipay Experience Design", a record of knowledge related to testing
Chrome安装zotero connector 插件
idea源码无法下载
ADB 安装 + 打驱动全教程
Embrace the Cmake child is simple and practical, but inflexible
SAP UI5 的初始化过程
基于单向链表结构的软件虚拟定时器的设计与构建
37.轮播图
Apache服务器配置多个站点
【CAS:2306109-91-9 |胺-PEG4-脱硫生物素】价格
「 WAIC 2022 · 黑客马拉松」蚂蚁财富两大赛题邀你来战!
在vs code中进行本地调试和开启本地服务器