当前位置:网站首页>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
边栏推荐
- SAP UI5 的初始化过程
- EasyUi常用代码
- JSD-2204-酷莎商城(管理员模块)-密码加密-Day10
- [Awards for Essays] Autumn recruitment special training to create your exclusive product experience
- 力扣题(5)—— 最长回文子串
- 【SQL】触发器同步表数据
- The book "The Essence of Alipay Experience Design", a record of knowledge related to testing
- Ant Group's time series database CeresDB is officially open source
- vs Code runs a local web server
- 遇到MapStruct后,再也不手写PO,DTO,VO对象之间的转换了
猜你喜欢
随机推荐
zynq records
ADB 安装 + 打驱动全教程
node 的运行命令
数据安全解决方案的发展
刷题-洛谷-P1307 数字反转
JS new一个构造器发生了什么?从零手写一个new方法
Unreal 本地化 国家化 多语言
C#弹出询问对话框
构建Buildroot根文件系统(I.MX6ULL)
The book "The Essence of Alipay Experience Design", a record of knowledge related to testing
vim clear last search highlighting
Chrome安装zotero connector 插件
刷题-洛谷-P1200 你的飞碟在这儿Your Ride Is Here
Desthiobiotin衍生物Desthiobiotin-PEG4-Amine/Alkyne/Azide/DBCO
Qt Designer生成的图形可以自适应窗口的大小变化
C#移动OA办公系统源码(基于微信企业号)
动态规划_双数组字符串
【有奖征文】秋招特训,打造你的专属产品体验
Tear down the underlying mechanism of the five JOINs of SparkSQL
如何使用 jMeter Parallel Controller - 并行控制器以及一些常犯的错误








