对象之间互相拷贝效率最高工具(mapstruct)
目录结构介绍
一:pom依赖
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.2.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.2.Final</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version> 1.18.20</version>
</dependency>
二:DO对象
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserDo implements Serializable {
private static final long serialVersionUID = 6110524897651597826L;
private int id;
private String name;
private int age;
private String address;
private String role;
private Date createDate;
private Date updateDate;
private String createUser;
private String updateUser;
}
三:Po对象
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserPo implements Serializable {
private static final long serialVersionUID = -3055967092435722132L;
private int id;
private String name;
private int age;
private String address;
private String role;
private Date createDate;
private Date updateDate;
private String createUser;
private String updateUser;
}
四:转换工具
BaseMapping
package com.example.demo.utils;
import org.mapstruct.InheritConfiguration;
import org.mapstruct.InheritInverseConfiguration;
import org.mapstruct.MapperConfig;
import java.util.List;
import java.util.stream.Stream;
@MapperConfig
public interface BaseMapping<SOURCE, TARGET> {
/**
* 映射同名属性
*/
TARGET sourceToTarget(SOURCE var1);
/**
* 反向,映射同名属性
*/
@InheritInverseConfiguration(name = "sourceToTarget")
SOURCE targetToSource(TARGET var1);
/**
* 映射同名属性,集合形式
*/
@InheritConfiguration(name = "sourceToTarget")
List<TARGET> sourceToTarget(List<SOURCE> var1);
/**
* 反向,映射同名属性,集合形式
*/
@InheritConfiguration(name = "targetToSource")
List<SOURCE> targetToSource(List<TARGET> var1);
/**
* 映射同名属性,集合流形式
*/
List<TARGET> sourceToTarget(Stream<SOURCE> stream);
/**
* 反向,映射同名属性,集合流形式
*/
List<SOURCE> targetToSource(Stream<TARGET> stream);
}
UserConverter
package com.example.demo.converter;
import com.example.demo.entity.UserDo;
import com.example.demo.po.UserPo;
import com.example.demo.utils.BaseMapping;
import org.mapstruct.Mapper;
/**
* @Description: do和po互相转换报告集合之前互相转换
* @Date: 2021/9/23 14:49
**/
@Mapper(componentModel = "spring")
public interface UserConverter extends BaseMapping<UserDo, UserPo> {
}
五:测试
/**
* 注入转换
*/
@Autowired
private UserConverter userConverter;
/**
* 实现Do映射Po,使用sourceToTarget
*/
@Test
void DoConverterPo() {
UserDo userDo = new UserDo();
userDo.setId(1);
userDo.setName("小明");
userDo.setAge(18);
userDo.setRole("学生");
userDo.setCreateDate(new Date());
userDo.setCreateUser("李白");
UserPo userPo = userConverter.sourceToTarget(userDo);
System.out.println("userPo = " + userPo);
//userPo = UserPo(id=1, name=小明, age=18, address=null, role=学生, createDate=Thu Sep 23 16:28:59 CST 2021, updateDate=null, createUser=李白, updateUser=null)
}
/**
* 实现Po映射Do,使用targetToSource
*/
@Test
void PoConverterDo() {
UserPo userPo = new UserPo();
userPo.setId(1);
userPo.setName("小明");
userPo.setAge(18);
userPo.setRole("学生");
userPo.setCreateDate(new Date());
userPo.setCreateUser("李白");
UserDo userDo = userConverter.targetToSource(userPo);
System.out.println("userDo = " + userDo);
//userDo = UserDo(id=1, name=小明, age=18, address=null, role=学生, createDate=Thu Sep 23 16:31:25 CST 2021, updateDate=null, createUser=李白, updateUser=null)
}
/**
* 实现Dos映射Pos,使用sourceToTarget
*/
@Test
void DoListConverterPoList() {
List<UserDo> userDos = new ArrayList<>();
UserDo userDo = new UserDo();
userDo.setId(1);
userDo.setName("小明");
userDo.setAge(18);
userDo.setRole("学生");
userDo.setCreateDate(new Date());
userDo.setCreateUser("李白");
UserDo userDo2 = new UserDo();
userDo2.setId(2);
userDo2.setName("大明");
userDo2.setAge(18);
userDo2.setRole("学生");
userDo2.setCreateDate(new Date());
userDo2.setCreateUser("李白");
userDos.add(userDo);
userDos.add(userDo2);
List<UserPo> userPos = userConverter.sourceToTarget(userDos);
System.out.println("userPos = " + userPos);
//userPos =
// [UserPo(id=1, name=小明, age=18, address=null, role=学生, createDate=Thu Sep 23 16:41:27 CST 2021, updateDate=null, createUser=李白, updateUser=null),
// UserPo(id=2, name=大明, age=18, address=null, role=学生, createDate=Thu Sep 23 16:41:27 CST 2021, updateDate=null, createUser=李白, updateUser=null)]
}
六:当对象中有字段不一致的情况时,需要重写方法
@Mapper(componentModel = "spring")
public interface UserConverter extends BaseMapping<UserDo, UserPo> {
@Mapping(target = "fatherName", source = "userExetend.fatherName")
@Mapping(target = "motherName", source = "userExetend.motherName")
@Mapping(target = "xiongDi", source = "brother")
@Override
UserPo sourceToTarget(UserDo var1);
}
源码:
注:在字段不一致手动映射时,打包失败,错误信息为:
Error:(22,12) java: No property named "fatherName" exists in source parameter(s). Did you mean "null"?。
第一位博主也出现过类似问题
第二位博主的友情提示
我也是有些奇怪,字段都是一样时使用没有任何问题,在这里踩了个坑。
mapstruct版本和lombok版本不一致导致。最后我将lombok版本降低为1.18.12问题就解决了。
此种搭配最终解决:
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.2.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.2.Final</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
踩坑指南:
clean install之后在生成的target文件下查看具体实现
如果出现映射丢失,或者没有映射主要排查如下情况:
1、lombok一定要放在mapstruct下面
2、检查lombok版本是否过低
测试时mapstuct版本为1.4.2.Final
lombok版本必须为1.16.16以上的高版本
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.2.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.2.Final</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
七:源码地址
八 扩展链接
1、干掉 BeanUtils!试试这款 Bean 自动映射工具,真心强大
2、mapstruct最佳实践
3、springboot整合mapstruct
4、SpringBoot 2.4.1整合 MapStruct 详细教程
5、MapStruct文档(九)——高级映射选项
6、MapStruct 1.3.0.Final参考指南