Mapstruct 简单对象之间映射(超详细)
一则小广告
最近,小哈正在带小伙伴做前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.2 + Vite 4
,手把手教学,前端 + 后端全栈开发,从 0 到 1 讲解每个功能开发过程,1v1 答疑,陪伴式直到项目上线,目前第六章 《Element Plus 手搭 Admin 后台管理骨架》已快完结,截止到目前,已更新 52 节内容,共计 81557 字,演示截图:433 张,持续更新中,后续还会上新更多项目,欢迎点击加入。
在项目中,我们经常会遇到需要把一个对象转换为另一个对象的需求,比如数据库对象转换成 DTO
(数据传输)对象。本小节中,小哈将演示如何使用 MapStruct 实现简单对象之间的映射。
1. 创建源对象和目标对象
首先,我们定义两个简单的 Java 对象:User
作为源对象和 UserDTO
作为目标对象。
源对象
public class User {
/**
* ID
*/
private Long id;
/**
* 用户名
*/
private String username;
/**
* 邮箱
*/
private String email;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", email='" + email + '\'' +
'}';
}
}
目标对象
public class UserDTO {
/**
* ID
*/
private Long id;
/**
* 用户名
*/
private String username;
/**
* 邮箱
*/
private String email;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "UserDTO{" +
"id=" + id +
", username='" + username + '\'' +
", email='" + email + '\'' +
'}';
}
}
注意:这里
User
和UserDTO
的字段名完全匹配的。
2. 定义映射接口
接下来,我们需要定义一个接口,MapStruct 会在编译时基于这个接口生成实际的映射类。
@Mapper
public interface UserConvert {
// 静态实例
UserConvert INSTANCE = Mappers.getMapper(UserConvert.class);
UserDTO toUserDTO(User user);
User toUser(UserDTO userDTO);
}
这里,我们使用了 @Mapper
注解来声明这是一个 MapStruct 映射器,并定义了两个映射方法。
3. 实现映射
由于 MapStruct 在编译时会为我们自动生成映射的实现,所以我们实际上不需要手动写这些实现代码。我们只需要在需要的地方通过 UserMapper.INSTANCE
调用映射方法即可。
我们可以执行 mvn clean compile
命令,看看编译后的源文件,是否已经自动生成了映射相关的代码:
Mapstruct 自动生成了映射代码
可以看到,Mapstruct 自动生成了 UserConvert
的实现类,相关映射方法也实现好了,终于不用手动 set
方法了。
4. 如何使用?
新建一个单元测试方法,使用方法如下:
@Test
public void testConvert() {
User user = new User();
user.setId(1L);
user.setEmail("quanxiaoha@qq.com");
user.setUsername("犬小哈");
UserDTO userDTO = UserConvert.INSTANCE.toUserDTO(user);
// 打印对象,看看是否映射成功
System.out.println(userDTO);
}
执行该单元测试,控制台输出如下:
可以看到字段都映射成功了。
5. 自定义字段映射
如果源对象和目标对象的字段名不完全匹配,MapStruct 提供了 @Mapping
注解来自定义字段之间的映射关系。
@Mapper
public interface UserConvert {
UserConvert INSTANCE = Mappers.getMapper(UserConvert.class);
@Mapping(source = "username", target = "name")
@Mapping(source = "email", target = "emailAddress")
@Mapping(source = "id", target = "identifier")
UserDTO toUserDTO(User user);
@Mapping(source = "name", target = "username")
@Mapping(source = "emailAddress", target = "email")
@Mapping(source = "identifier", target = "id")
User toUser(UserDTO userDTO);
}
这里,source
是源对象的字段名,target
是目标对象的字段名。
6. 小结
MapStruct 为我们提供了一个简洁、高效的方式来实现对象之间的映射。它遵循“约定优于配置”的原则,对于大多数常见的映射场景,我们不需要写任何实现代码。当需要自定义映射时,MapStruct 也提供了灵活而强大的配置选项。