当前位置:网站首页>遇到MapStruct后,再也不手写PO,DTO,VO对象之间的转换了
遇到MapStruct后,再也不手写PO,DTO,VO对象之间的转换了
2022-08-04 20:20: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
转换的时候指定方法
当我们想把PersonVO转换为PersonPO,PersonPO中的gender是一个枚举,PersonVO中的gender是一个int类型,如何把枚举转为枚举的value值呢?
在@Mapping注解中通过qualifiedByName属性指定转换的方法
@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
边栏推荐
- C#移动OA办公系统源码(基于微信企业号)
- really time ntp service start command
- vim clear last search highlighting
- Seata source code analysis: various message processing processes of seata server
- Red5搭建直播平台
- 使用 Chrome 开发者工具 coverage 功能分析 web 应用的渲染阻止资源的执行分布情况
- 如何找到某个 ABAP structure 某字段的源头来自哪个数据库表
- win10 uwp modify picture quality compress picture
- vscode离线安装插件方法
- nr部分计算
猜你喜欢
实现菜单拖拽排序
【CAS:2306109-91-9 |胺-PEG4-脱硫生物素】价格
Use "green computing" technology to promote sustainable development of computing power
Tear down the underlying mechanism of the five JOINs of SparkSQL
刷题-洛谷-P1319 压缩技术
新式茶饮,卷完水果还能卷什么?
二叉树是否对称
KubeSphere简介,功能介绍,优势,架构说明及应用场景
Chrome安装zotero connector 插件
hash和history路由的区别
随机推荐
composition-api
面试官:JVM运行时数据区包含哪几部分?作用是啥?
Force KouTi (5), the longest text string back
Desthiobiotin衍生物Desthiobiotin-PEG4-Amine/Alkyne/Azide/DBCO
Chrome安装zotero connector 插件
JSD-2204-酷莎商城(管理员模块)-密码加密-Day10
hash和history路由的区别
简单理解 JS 事件循环
小软件大作用 | 如何省时省力进行Gerber图层快速对比?
ASP.NET商贸进销存管理系统源码(带数据库文档)源码免费分享
Apache服务器的配置[通俗易懂]
新式茶饮,卷完水果还能卷什么?
IIC驱动OLED
Client Side Cache 和 Server Side Cache 的区别
MYSQL获取数据库的表名和表注释
Zero-knowledge proof notes - private transaction, pederson, interval proof, proof of ownership
刷题-洛谷-P1179 数字统计
如何使用 jMeter Parallel Controller - 并行控制器以及一些常犯的错误
really time ntp服务启动命令
面试官:索引为什么会失效?