mapstruct 无法生成字段映射code
文章目录
- 前言-随便写点
- 一、maven
- 二、搞个基类
- 1. BaseMapping
- 2. ExtendMapping
- 3. 使用示例
- 三、没有生成字段映射?
- 总结
前言-随便写点
MapStruct 是一个 Java 注释处理器,用于生成类型安全的 bean 映射类。
您所要做的就是定义一个映射器接口,该接口可以声明任何您所需的映射方法。在编译期间,MapStruct 将生成此接口的实现。这个实现使用普通的 Java 方法调用(get,set方法)来映射源对象和目标对象,而不是使用反射。
项目编译后generated-sources\annotations路径下会找到编译后的文件,这里会对两个对象的属性一一set
一、maven
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
</dependency>
二、搞个基类
1. BaseMapping
import org.mapstruct.*;
import java.util.ArrayList;
import java.util.List;
/**
* <p>
* MapStruct映射基类,直接继承接口即可使用通用方法,针对性指定需在继承类的接口方法上指定
* <p>
* 例: public interface xxxMapping extends BaseMapping<xxxDO, xxxDTO>
* <p>
* 具体用法可参考单元测试,建议配合MapStruct Support插件使用
*/
@MapperConfig(componentModel = "spring")
public interface BaseMapping<F, T> {
/**
* 正向映射
*/
@InheritConfiguration
T convertTo(F obj);
/**
* 反向映射
*/
@InheritInverseConfiguration(name = "convertTo")
F convertFrom(T obj);
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
void supplementFrom(T t, @MappingTarget F f);
/**
* 正向映射(List)
*/
default List<T> convertTo(List<F> list) {
if (list == null) {
return null;
}
List<T> result = new ArrayList<T>(list.size());
for (F f : list) {
if (f == null) {
continue;
}
result.add(convertTo(f));
}
return result;
}
/**
* 反向映射(List)
*/
default List<F> convertFrom(List<T> list) {
if (list == null) {
return null;
}
List<F> result = new ArrayList<F>(list.size());
for (T t : list) {
if (t == null) {
continue;
}
result.add(convertFrom(t));
}
return result;
}
/**
* 正向映射的后置处理,List映射会自动继承此配置
*/
@AfterMapping
default void handleAfterConvertTo(F src, @MappingTarget T dest) {
afterConvertTo(src, dest);
}
/**
* 反向映射的后置处理,List映射会自动继承此配置
*/
@AfterMapping
default void handleAfterConvertFrom(T src, @MappingTarget F dest) {
afterConvertFrom(src, dest);
}
/**
* 正向映射的后置处理,List映射会自动继承此配置
*/
default void afterConvertTo(F src, T dest) {
//TODO 覆盖此方法处理其他复杂转换逻辑
}
/**
* 反向映射的后置处理,List映射会自动继承此配置
*/
default void afterConvertFrom(T src, F dest) {
//TODO 覆盖此方法处理其他复杂转换逻辑
}
}
2. ExtendMapping
import org.mapstruct.*;
import java.util.ArrayList;
import java.util.List;
/**
* <p>
* MapStruct映射基类,直接继承接口即可使用通用方法,针对性指定需在继承类的接口方法上指定
* <p>
* 例: public interface xxxMapping extends BaseMapping<PO, Req, Resp>
* <p>
*
*/
@MapperConfig(componentModel = "spring")
public interface ExtendMapping<PO, Req, Resp> {
Resp po2Resp(PO obj);
PO req2PO(Req obj);
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
void supplementPO(Req req, @MappingTarget PO PO);
default List<Resp> po2Resp(List<PO> list) {
if (list == null) {
return null;
}
List<Resp> result = new ArrayList<>(list.size());
for (PO PO : list) {
if (PO == null) {
continue;
}
result.add(po2Resp(PO));
}
return result;
}
default List<PO> req2PO(List<Req> list) {
if (list == null) {
return null;
}
List<PO> result = new ArrayList<>(list.size());
for (Req req : list) {
if (req == null) {
continue;
}
result.add(req2PO(req));
}
return result;
}
/**
* 转换Resp的前置处理
*/
@BeforeMapping
default void handleBeforePo2Resp(PO src, @MappingTarget Resp target) {
before2Resp(src, target);
}
/**
* 转换Resp的后置处理
*/
@AfterMapping
default void handleAfterPo2Resp(PO src, @MappingTarget Resp target) {
after2Resp(src, target);
}
/**
* 转换PO的前置处理
*/
@BeforeMapping
default void handleBeforeReq2PO(Req src, @MappingTarget PO target) {
before2PO(src, target);
}
/**
* 转换PO的后置处理
*/
@AfterMapping
default void handleAfterReq2PO(Req src, @MappingTarget PO target) {
after2PO(src, target);
}
default void before2Resp(PO src, Resp target) {
//TODO 覆盖此方法处理其他复杂转换逻辑
}
default void before2PO(Req src, PO dest) {
//TODO 覆盖此方法处理其他复杂转换逻辑
}
default void after2Resp(PO src, Resp target) {
//TODO 覆盖此方法处理其他复杂转换逻辑
}
default void after2PO(Req src, PO dest) {
//TODO 覆盖此方法处理其他复杂转换逻辑
}
}
3. 使用示例
@Mapper(componentModel = "spring")
public interface BisMenuMapping extends ExtendMapping<BisMenuPO, BisMenuReq, BisMenuResp> {
}
三、没有生成字段映射?
查看target\generated-sources\annotations下生成的类,发现只创建了一个空对象,没有生成任何set代码。
这里用到了lombok
排查发现,maven引用的时候先引用的mapstruct后lombok,导致mapstruct构建set code的时候,对象的get set方法还没有被lombok生成,导致此问题。
解决办法:
先引用lombok,后mapstruct 或者maven plugin 指定编译顺序。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
总结
在lombok和mapstruct同时使用时,一定要注意将编译顺序指定一下,不然mapstruct无法生成实现类无法使用。