前言

MapStruct是一个Java编译器插件的注解处理器,可以快速便捷的实现实体类的转换。比如VO和DTO之间的互转。

官网

引入依赖

最新版本号可以去官网获取

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>

快速使用

创建一个接口,作为MapStruct构建的接口。

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
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;

import java.util.List;

@Mapper
public interface CategoryMapping {
CategoryMapping INSTANCE = Mappers.getMapper(CategoryMapping.class);


CategoryVO category2VO(Category category);

/**
* 如果转换前后的实体类参数不同,可以通过@Mapping注解指定对于的映射关系
* source表示源对象的属性,及形参中的Category对象的属性
* target表示目标对象的属性,及转换后的CategoryDTO对象中的属性
*/
@Mapping(source = "name", target = "displayName")
CategoryDTO category2DTO(Category category);

/**
* 对于List也是可以直接实现转换
*/
@Mapping(source = "name", target = "displayName")
List<CategoryDTO> categories2DTO(List<Category> categories);

}

实体类示例:

1
2
3
4
5
6
7
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Category {
private Long id;
private String name;
}
1
2
3
4
5
6
7
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CategoryVO {
private Long id;
private String name;
}
1
2
3
4
5
6
7
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CategoryDTO {
private Long id;
private String displayName;
}

需要注意的是MapStruct会在项目构建时自动生成实现类:

图片

测试:

1
2
3
4
5
6
7
8
9
10
11
12
@Test
void contextLoads() {
Category category = new Category(999L, "ahzoo");
Category category2 = new Category(9L, "十玖八柒");
ArrayList<Category> list = new ArrayList<>();
list.add(category);
list.add(category2);
CategoryDTO categoryDTO = CategoryMapping.INSTANCE.category2DTO(category);
CategoryVO categoryVO = CategoryMapping.INSTANCE.category2VO(category);
List<CategoryDTO> categoryDTOS = CategoryMapping.INSTANCE.categories2DTO(list);
System.out.println(categoryDTO);
}

图片

后记

报错:No property named “XXX“ exists in source parameter(s). Did you mean “null“?

原因及解决方式:项目中使用了较低版本的Lombok,升级Lombok版本即可

报错:Couldn’t retrieve @Mapper annotation

原因及解决方式:mapstruct包重复引入,检查其它依赖包中是否含有mapstruct依赖,排除掉重复的依赖包即可。

其它问题

实体类转换后,属性为null

打开编译后的实现类文件,可以发现实现类中只使用new创建了一个对象,却并未对属性赋值,所以转换后的对象是个空的对象:

图片

原因及解决方法:项目中引入了Lombok依赖,需要将Lombok依赖放在MapStruct依赖的前面。