MapStruct 是一个 Java 注释处理器,用于为 Java Bean 类生成类型安全和高性能的映射器。可以自动编写映射代码,处理常见实体类的属性映射很方便。
目录
一、Maven依赖
<!-- 与lombok不冲突的版本 -->
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<optional>true</optional>
</dependency>
<!-- mapstruct -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.3.0.Final</version>
</dependency>
<!-- -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
<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.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
二、基本转换
演示实体类:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class RoleDto {
@ApiModelProperty("id")
private Integer id;
/**
* 角色名
*/
@ApiModelProperty("角色名")
private String roleName;
/**
* 描述
*/
@ApiModelProperty("描述")
private String remark;
}
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Role implements Serializable {
@ApiModelProperty("id")
private Integer id;
@ApiModelProperty("角色名")
private String roleName;
@ApiModelProperty("描述")
private String description;
@ApiModelProperty("创建时间")
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createtime;
@ApiModelProperty("更新时间")
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updatetime;
}
1、相同属性名(实体类、List)
当相互转换的实体类的属性名相同时,可以直接写方法:
//注意注解导包import org.mapstruct.Mapper;
@Mapper
public interface RoleCovert {
RoleCovert INSTANCE= Mappers.getMapper(RoleCovert.class);
// 将对象Role中的属性映射到RoleDto中 (Role中没有remark同名属性,不会映射)
RoleDto toCovertRole(Role role);
// 如果需要进行list转换,需要在上面方法的基础上添加一个list方法即可,会利用上述方法转换
List<RoleDto> toCovertRole(List<Role> roles);
}
生成的实体类:
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2023-04-12T19:26:11+0800",
comments = "version: 1.3.0.Final, compiler: javac, environment: Java 1.8.0_131 (Oracle Corporation)"
)
public class RoleCovertImpl implements RoleCovert {
@Override
public RoleDto toCovertRole(Role role) {
if ( role == null ) {
return null;
}
RoleDto roleDto = new RoleDto();
roleDto.setId( role.getId() );
roleDto.setRoleName( role.getRoleName() );
return roleDto;
}
@Override
public List<RoleDto> toCovertRole(List<Role> roles) {
if ( roles == null ) {
return null;
}
List<RoleDto> list = new ArrayList<RoleDto>( roles.size() );
for ( Role role : roles ) {
list.add( toCovertRole( role ) );
}
return list;
}
}
2、不同属性名(实体类、List)
将Role中的description属性映射到RoleDto的remark属性,需要加注解@Mapping:
@Mapping 可以指定某些特殊映射(@Mapping可以直接加在方法上,也可以选择在方法上加@Mappings包裹@Mapping)
@Mapper
public interface RoleCovert {
RoleCovert INSTANCE= Mappers.getMapper(RoleCovert.class);
//将Role中的description属性映射到RoleDto的remark属性
@Mapping(target = "remark",source = "description")
RoleDto toCovertRole(Role role);
List<RoleDto> toCovertRole(List<Role> roles);
}
3、自定义属性值
@Mapping 也可以设置属性默认常量,或expression表达式设置属性值(如获取当前时间、参数进行某些处理等)
// 将目标类的deleted属性值为常量0
@Mapping(target = "deleted", constant = "0")
// 将目标类的createtimed属性值为当前时间
@Mapping(target = "createtime", expression = "java(java.time.LocalDateTime.now())")
4、多参数转换
在多个参数属性名不重复,且与目标实体类要映射的属性相同时可以直接使用,否则也可以用注解的方式
@Mappings({
将role实体的id值映射到目标实体的roleId属性
@Mapping(target = "roleId", source = "role.id"),
@Mapping(target = "permissionId", source = "permission.id")
})
RolePermission toCovert(Role role, Permission permission);
5、List转换且其一为固定参数的情况
有时实体类会是联系表,其中A关联Id固定,B为List,然后转换为联系实体List<A_B>:
需要将A固定的Id加 @Context注解,然后再在 @Mapping里用expression = "java(A_Id)"设值。
@Mapper
public interface RolePermissionCovert {
RolePermissionCovert INSTANCE = Mappers.getMapper(RolePermissionCovert.class);
// 单实体转换,设置某一属性值固定,之后List也在固定值加@Context注解即可
// 这里的用的Integer,实际上可以用实体类
@Mapping(target = "roleId",expression = "java(roleId)")
RolePermission toCovert(Integer permissionId, @Context Integer roleId);
List<RolePermission> toCovert(List<Integer> permissionIds, @Context Integer roleId);
}
生成的实体类
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2023-04-12T19:26:11+0800",
comments = "version: 1.3.0.Final, compiler: javac, environment: Java 1.8.0_131 (Oracle Corporation)"
)
public class RolePermissionCovertImpl implements RolePermissionCovert {
@Override
public RolePermission toCovert(Integer permissionId, Integer roleId) {
if ( permissionId == null ) {
return null;
}
RolePermission rolePermission = new RolePermission();
rolePermission.setPermissionId( permissionId );
rolePermission.setRoleId( roleId );
return rolePermission;
}
@Override
public List<RolePermission> toCovert(List<Integer> permissionIds, Integer roleId) {
if ( permissionIds == null ) {
return null;
}
List<RolePermission> list = new ArrayList<RolePermission>( permissionIds.size() );
for ( Integer integer : permissionIds ) {
list.add( toCovert( integer, roleId ) );
}
return list;
}
}