遇到MapStruct后,再也不手写PO,DTO,VO对象之间的转换了
点击上方 好好学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);
}
新建一个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);
}
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对象之间的转换了相关推荐
- CSDN-markdown写博客使用LaTeX语法编写数学公式(再也不怕手写公式,以后博客手写复杂公式就靠它了!)
LaTeX数学公式语法目录 一.希腊字母表 二.常用函数举例 三.集合 四.常用逻辑与箭头 五.括号 六.矩阵.多行列式 七.常用戴帽.矢量符号 八.微积分运算符 九.字体种类 十.关系符号 十一.更 ...
- 手写springioc注解注入对象基本实现
还是要养成写注释的习惯,首先一个代码想让人家看懂的情况下,记住一点,重构加设计模式,其实设计模式也比较好,达到别人可易读性,这是我要跟你讲的,而且你们不写注释是一个不好的习惯,你们一定要养成我善于重构 ...
- 【纸上得来终觉浅】RoundRobinRule源码分析后,自己手写了轮询算法
前言 今天自己查看了RoundRobinRule的源码,通过读源码走断点,大概自己知道了源码中,参数调用,下面我是查阅相关源代码,反正看过源代码以后总感觉纸上得来终觉浅,绝知此事要躬行,然后编写了轮询 ...
- 手写springiocxml方式注入对象
什么是SpringIOC spring ioc指的是控制反转,IOC容器负责实例化.定位.配置应用程序中的对象及建立这些对象间的依赖. 交由Spring来管理这些,实现解耦 SpringIOC原理 使 ...
- 不知道怎么识别手写文字?快来看这些手写文字识别成文档软件
平时在上课的时候,我们经常需要通过记笔记的方式将老师讲的课堂知识点记录下来,方便课后复习巩固.而有些勤奋的小伙伴为了能够时时刻刻进行复习,还会将纸质笔记整理成电子版便于日常查看.其实他们正是通过一些识 ...
- 现代C++之手写智能指针
现代C++之手写智能指针 0.回顾 所有代码还是放在仓库里面,欢迎star! https://github.com/Light-City/CPlusPlusThings 前面一节编写了一个RAII的例 ...
- 手写HashMap,快手面试官直呼内行
手写HashMap?这么狠,面试都卷到这种程度了? 第一次见到这个面试题,是在某个不方便透露姓名的Offer收割机大佬的文章: 这--我当时就麻了,我们都知道HashMap的数据结构是数组+链表+红黑 ...
- 面试表演了手写HashMap,把面试官给秀到了
手写HashMap?这么狠,面试都卷到这种程度了? 第一次见到这个面试题,是在某个不方便透露姓名的Offer收割机大佬的文章: 手写HashMap,快手一面卒 这--我当时就麻了,我们都知道HashM ...
- 安卓pdf阅读器_用户分享Note2阅读器体验:全格式手写、双开翻译功能很给力!...
本文出自百度贴吧用户 "猫叔" 对 BOOX Note2的评测,已征得作者授权转载. 楼主是电纸书阅读器爱好者,使用过kindle paper2,kindle oasis2,文石p ...
最新文章
- ORA-07445 [kkoipt()+3881] [SIGSEGV] [Address not mapped to object] 问题
- wps右键新建里面没有word和excel_wps常用的基本操作方法
- 设计模式读书笔记-----代理模式
- 计算机学习的基本形式,电脑基础知识学习方法
- seaborn.heatmap概述
- jquery 数组indexof_如何实现一个简化版的 jQuery
- eplan安装提示没有安装许可语言_CAD和EPLAN!电气制图你会选择哪个?
- html文本框最小数字,HTML5中的数字类型的输入框:数字选择器
- 回归预测值预测区间_机器学习之线性回归概述
- 汉字笔顺口诀_【小学语文知识】汉字书写笔顺口诀+书写规则
- 数据传递-------@ModelAttribute
- php cgi启动报错,php编译安装,cgi启动,以及memcache扩展编译安装.
- CRC检验码计算——C语言(CRC8/16/32)
- Flask流式传输文件
- 前端微信支付代码(公众号支付)
- 没有对象怎么面向对象编程呢?真让人头秃!
- 参考牛顿冷却定律优化最热问题的排序
- 计算机主板电感有正负极么,功率电感有没有方向?正负极区分
- vyos-vyatta在ospf和bgp之间路由重发布使用 打tag形式进行路由过滤
- 微信小程序 - 一键复制功能
热门文章
- ble之gatt server
- 萤石的云存储到期怎么启动内存卡_3款萤石智能入户单品 让普通入户门秒变智能...
- R语言:na.fail和na.omit
- 《研磨设计模式》chap11 代理proxy模式
- sh256sum、xxd、base64联合计算文件的hash
- 【Flask】flask入门以及第一个flask项目的创建
- 栈——用链表实现栈操作
- Android Gatekeeper流程深度解剖
- android classloader异常,Android中ClassLoader类加载机制
- 宝塔 mysql迁移_(2020年最新方法)如何快速迁移网站?使用宝塔一键迁移转移网站数据详细教程...