点击上方 好好学java ,选择 星标 公众号

重磅资讯、干货,第一时间送达

今日推荐:腾讯推出高性能 RPC 开发框架

个人原创100W+访问量博客:点击前往,查看更多

介绍

在工作中,我们经常要进行各种对象之间的转换。

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>

对象互转

@Data
@Builder
public class StudentPO {private Integer id;private String name;private Integer age;private String className;
}

@Data
public class StudentVO {private Integer id;private String studentName;private Integer studentAge;private String schoolName;
}

@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. 新建一个Mapper接口,上面加上@Mapper注解

  2. 新建一个成员变量INSTANCE

  3. 用@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);
}

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);
}

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);
}

多个对象映射一个对象

我们用SchoolPO和StudentPO来映射SchoolStudentVO

@Data
@Builder
public class SchoolPO {private String name;private String location;
}

@Data
@Builder
public class StudentPO {private Integer id;private String name;private Integer age;private String className;
}

@Data
public class SchoolStudentVO {private String schoolName;private String studentName;
}

@Mapper
public interface StudentMapper {@Mappings({@Mapping(source = "schoolPO.name", target = "schoolName"),@Mapping(source = "studentPO.name", target = "studentName")})SchoolStudentVO mergeVo(SchoolPO schoolPO, StudentPO studentPO);
}

测试例子如下

@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);
}

当然还有其他的骚操作,这里就简单介绍一些比较实用的技巧,有兴趣的可以看官方的example

https://github.com/mapstruct/mapstruct-examples

实现原理

MapStruct帮你对接口生成了一个实现类,下面就是生成的实现类,从class文件夹中可以看到

public class StudentMapperImpl implements StudentMapper {public StudentMapperImpl() {}public StudentVO po2Vo(StudentPO studentPO) {if (studentPO == null) {return null;} else {StudentVO studentVO = new StudentVO();studentVO.setStudentAge(studentPO.getAge());studentVO.setStudentName(studentPO.getName());studentVO.setId(studentPO.getId());return studentVO;}}public List<StudentVO> poList2VoList(List<StudentPO> studentPO) {if (studentPO == null) {return null;} else {List<StudentVO> list = new ArrayList(studentPO.size());Iterator var3 = studentPO.iterator();while(var3.hasNext()) {StudentPO studentPO1 = (StudentPO)var3.next();list.add(this.po2Vo(studentPO1));}return list;}}public SchoolStudentVO mergeVo(SchoolPO schoolPO, StudentPO studentPO) {if (schoolPO == null && studentPO == null) {return null;} else {SchoolStudentVO schoolStudentVO = new SchoolStudentVO();if (schoolPO != null) {schoolStudentVO.setSchoolName(schoolPO.getName());}if (studentPO != null) {schoolStudentVO.setStudentName(studentPO.getName());}return schoolStudentVO;}}
}
最后,再附上我历时三个月总结的 Java 面试 + Java 后端技术学习指南,笔者这几年及春招的总结,github 1.4k star,拿去不谢!下载方式1. 首先扫描下方二维码
2. 后台回复「Java面试」即可获取

遇到MapStruct后,再也不手写PO,DTO,VO对象之间的转换了相关推荐

  1. CSDN-markdown写博客使用LaTeX语法编写数学公式(再也不怕手写公式,以后博客手写复杂公式就靠它了!)

    LaTeX数学公式语法目录 一.希腊字母表 二.常用函数举例 三.集合 四.常用逻辑与箭头 五.括号 六.矩阵.多行列式 七.常用戴帽.矢量符号 八.微积分运算符 九.字体种类 十.关系符号 十一.更 ...

  2. 手写springioc注解注入对象基本实现

    还是要养成写注释的习惯,首先一个代码想让人家看懂的情况下,记住一点,重构加设计模式,其实设计模式也比较好,达到别人可易读性,这是我要跟你讲的,而且你们不写注释是一个不好的习惯,你们一定要养成我善于重构 ...

  3. 【纸上得来终觉浅】RoundRobinRule源码分析后,自己手写了轮询算法

    前言 今天自己查看了RoundRobinRule的源码,通过读源码走断点,大概自己知道了源码中,参数调用,下面我是查阅相关源代码,反正看过源代码以后总感觉纸上得来终觉浅,绝知此事要躬行,然后编写了轮询 ...

  4. 手写springiocxml方式注入对象

    什么是SpringIOC spring ioc指的是控制反转,IOC容器负责实例化.定位.配置应用程序中的对象及建立这些对象间的依赖. 交由Spring来管理这些,实现解耦 SpringIOC原理 使 ...

  5. 不知道怎么识别手写文字?快来看这些手写文字识别成文档软件

    平时在上课的时候,我们经常需要通过记笔记的方式将老师讲的课堂知识点记录下来,方便课后复习巩固.而有些勤奋的小伙伴为了能够时时刻刻进行复习,还会将纸质笔记整理成电子版便于日常查看.其实他们正是通过一些识 ...

  6. 现代C++之手写智能指针

    现代C++之手写智能指针 0.回顾 所有代码还是放在仓库里面,欢迎star! https://github.com/Light-City/CPlusPlusThings 前面一节编写了一个RAII的例 ...

  7. 手写HashMap,快手面试官直呼内行

    手写HashMap?这么狠,面试都卷到这种程度了? 第一次见到这个面试题,是在某个不方便透露姓名的Offer收割机大佬的文章: 这--我当时就麻了,我们都知道HashMap的数据结构是数组+链表+红黑 ...

  8. 面试表演了手写HashMap,把面试官给秀到了

    手写HashMap?这么狠,面试都卷到这种程度了? 第一次见到这个面试题,是在某个不方便透露姓名的Offer收割机大佬的文章: 手写HashMap,快手一面卒 这--我当时就麻了,我们都知道HashM ...

  9. 安卓pdf阅读器_用户分享Note2阅读器体验:全格式手写、双开翻译功能很给力!...

    本文出自百度贴吧用户 "猫叔" 对 BOOX Note2的评测,已征得作者授权转载. 楼主是电纸书阅读器爱好者,使用过kindle paper2,kindle oasis2,文石p ...

最新文章

  1. ORA-07445 [kkoipt()+3881] [SIGSEGV] [Address not mapped to object] 问题
  2. wps右键新建里面没有word和excel_wps常用的基本操作方法
  3. 设计模式读书笔记-----代理模式
  4. 计算机学习的基本形式,电脑基础知识学习方法
  5. seaborn.heatmap概述
  6. jquery 数组indexof_如何实现一个简化版的 jQuery
  7. eplan安装提示没有安装许可语言_CAD和EPLAN!电气制图你会选择哪个?
  8. html文本框最小数字,HTML5中的数字类型的输入框:数字选择器
  9. 回归预测值预测区间_机器学习之线性回归概述
  10. 汉字笔顺口诀_【小学语文知识】汉字书写笔顺口诀+书写规则
  11. 数据传递-------@ModelAttribute
  12. php cgi启动报错,php编译安装,cgi启动,以及memcache扩展编译安装.
  13. CRC检验码计算——C语言(CRC8/16/32)
  14. Flask流式传输文件
  15. 前端微信支付代码(公众号支付)
  16. 没有对象怎么面向对象编程呢?真让人头秃!
  17. 参考牛顿冷却定律优化最热问题的排序
  18. 计算机主板电感有正负极么,功率电感有没有方向?正负极区分
  19. vyos-vyatta在ospf和bgp之间路由重发布使用 打tag形式进行路由过滤
  20. 微信小程序 - 一键复制功能

热门文章

  1. ble之gatt server
  2. 萤石的云存储到期怎么启动内存卡_3款萤石智能入户单品 让普通入户门秒变智能...
  3. R语言:na.fail和na.omit
  4. 《研磨设计模式》chap11 代理proxy模式
  5. sh256sum、xxd、base64联合计算文件的hash
  6. 【Flask】flask入门以及第一个flask项目的创建
  7. 栈——用链表实现栈操作
  8. Android Gatekeeper流程深度解剖
  9. android classloader异常,Android中ClassLoader类加载机制
  10. 宝塔 mysql迁移_(2020年最新方法)如何快速迁移网站?使用宝塔一键迁移转移网站数据详细教程...