1. 概述
MapStruct 是一个代码生成器,它基于约定优于配置方法极大地简化了 Java bean 类型之间映射的实现。方便pojo、vo、dto与实体类之间的相互转换。更多详情请参阅官网
优缺点
- MapStruct在编译的时候生成映射的代码,如果有错误会在编译时就发现
- 底层使用get/set方法,而非反射方式,执行时效率更快
- 可以实现深拷贝,修改新对象时不会对老对象产生影响
- 类型更加安全,只能映射相互映射的对象和属性,可以进行自定义的类型和字段映射
- 需要额外新增一个接口或者抽象类
2. 引入核心依赖
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<mapstruct.version>1.4.2.Final</mapstruct.version>
<lombok.version>1.18.20</lombok.version>
<lombok-mapstruct.version>0.2.0</lombok-mapstruct.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>${lombok-mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
3. 新建实体类和dto对象
@Getter
@Setter
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class SysUserInfo {
/**
* 主键ID
*/
private Long id;
/**
* 用户名称
*/
private String userName;
/**
* 性别0:男;1:女;2:未知
*/
private SexEnum sex;
/**
* 邮箱
*/
private String email;
/**
* 手机号
*/
private String phonenumber;
/**
* 头像
*/
private String avatar;
/**
* 状态0:正常;1:停用
*/
private Integer status;
/**
* 薪水
*/
private BigDecimal salary;
/**
* 创建者
*/
private String createUser;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新者
*/
private String updateUser;
}
@Getter
@Setter
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class UserVo {
/**
* 主键ID
*/
private String id;
/**
* 用户名称
*/
private String userName;
/**
* 密码
*/
private String password;
/**
* 性别0:男;1:女;2:未知
*/
private String sex;
/**
* 邮箱
*/
private String email;
/**
* 手机号
*/
private String phone;
/**
* 头像
*/
private String avatar;
/**
* 状态
*/
private String status;
/**
* 薪水
*/
private String salary;
/**
* 创建者
*/
private String createUser;
/**
* 创建时间
*/
private String createTime;
/**
* 更新者
*/
private String updateUser;
/**
* 更新时间
*/
private String updateTime;
}
4. 新建映射接口
@Mapper
public interface SysUserInfoMapper {
SysUserInfoMapper INFO_MAPPER = Mappers.getMapper(SysUserInfoMapper.class);
@Mapping(target = "id", defaultValue = "1")
@Mapping(target = "password", ignore = true)
@Mapping(source = "phonenumber", target = "phone")
@Mapping(source = "sex.value", target = "sex")
@Mapping(target = "status", constant = "正常")
@Mapping(target = "salary", numberFormat = "#.00")
@Mapping(target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
@Mapping(source = "userInfo", target = "updateTime", qualifiedByName = "now")
UserVo map(SysUserInfo userInfo);
@Named("now")
default LocalDateTime now(Object source) {
return LocalDateTime.now();
}
}
5. 测试
@SpringBootTest
public class MapStructApplicationTest {
@Test
void userTest() {
SysUserInfo userInfo = SysUserInfo.builder()
.id(1L)
.userName("zhangsan")
.sex(SexEnum.MALE)
.email("[email protected]")
.status(0)
.salary(new BigDecimal(12000))
.phonenumber("13898767890")
.createUser("admin")
.createTime(LocalDateTime.now())
.updateUser("admin")
.build();
UserVo userVo = SysUserInfoMapper.INFO_MAPPER.map(userInfo);
System.out.println(userVo.toString());
Assertions.assertNotNull(userVo);
}
}
6. 扩展
Mapper接口可以使用工厂方法注入,也可以使用依赖注入方式,如下所示:
@Mapper(componentModel = "spring")
public interface SysUserInfoMapper {
@Mapping(target = "id", defaultValue = "1")
@Mapping(target = "password", ignore = true)
@Mapping(source = "phonenumber", target = "phone")
@Mapping(source = "sex.value", target = "sex")
@Mapping(target = "status", constant = "正常")
@Mapping(target = "salary", numberFormat = "#.00")
@Mapping(target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
@Mapping(source = "userInfo", target = "updateTime", qualifiedByName = "now")
UserVo map(SysUserInfo userInfo);
@Named("now")
default LocalDateTime now(Object source) {
return LocalDateTime.now();
}
}
使用时只需要按照普通接口注入就行
@Mapping注解属性值解释
source:数据源
target:目标对象
defaultValue:用于设置默认值
constant:用于设置常量
numberFormat:用于设置数据格式
dateFormat:用于设置日期格式
qualifiedByName:用于自定义命名