我有两个映射器,
MapperOne
和MapperTwo
,后者取决于前者:
@Mapper(componentModel = "spring")
public interface MapperOne {
UserDTO convert(User user);
}
@Mapper(componentModel = "spring", uses = MapperOne.class)
public interface MapperTwo {
@Mapping(target = "loginUser", source = "user")
UserDTO convert(Login login);
}
MapperTwo
按预期工作,但我们假设第三个映射器使用 MapperTwo
,如下所示:
import static org.mapstruct.factory.Mappers.getMapper;
@Mapper(componentModel = "spring")
public interface MapperThree {
default UserDTO convert(@NonNull final LoginWrapper loginWrapper) {
final Login login = loginWrapper.getInstance();
return getMapper(MapperTwo.class).convert(login);
}
}
MapperThree
不起作用,我总是收到以下错误消息:
java.lang.NullPointerException:无法调用 “com.mytest.mappers.MapperOne.convert(com.mytest.User)”因为 “this.mapperOne”为空
当您使用
componentModel = "spring"
时,您不应该使用Mappers.getMapper
。使用通常的 @Autowired
或通过构造函数进行依赖注入应该可以。这可能就是您的案例遇到问题的原因。只需使用 uses = {SomeMapper.class}
就可以了。当类型适用时,Mapstruct 将自动使用“已使用”映射器的映射。
如果您想真正在另一个映射器中编写默认函数,那么您应该使用抽象类并像往常一样自动装配另一个映射器。
@Mapper(componentModel = "spring")
public abstract class MapperThree {
@Autowired
MapperTwo mapperTwo;
default UserDTO convert(@NonNull final LoginWrapper loginWrapper) {
final Login login = loginWrapper.getInstance();
return mapperTwo.convert(login);
}
}
在 pom.xml 中定义属性: 将属性添加到您的 pom.xml 中:
<properties>
<mapstruct.defaultComponentModel>spring</mapstruct.defaultComponentModel>
</properties>
配置Maven编译器插件: 添加配置以将此属性传递给注释处理器,这样您就不必在每个映射器中重复包含 componentModel=spring :
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version> <!-- Use the appropriate version -->
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.5.Final</version>
</path>
</annotationProcessorPaths>
<annotationProcessorOptions>
<mapstruct.defaultComponentModel>${mapstruct.defaultComponentModel}</mapstruct.defaultComponentModel>
</annotationProcessorOptions>
</configuration>
</plugin>
</plugins>
</build>
MapperOne不需要改变。
@Mapper
public interface MapperOne {
UserDTO convert(User user);
}
MapperTwo:您能否确认所需的返回值是 UserDTO 而不是 LoginDTO 或类似的值?
@Mapper(uses = {MapperOne.class})
public interface MapperTwo {
@Mapping(target = "loginUser", source = "user")
UserDTO convert(Login login);
}
假设您需要一些转换器方法并希望依赖于另一个映射器,您可以定义一个抽象类并通过 setter 注入自动装配。
@Mapper(uses = MapperTwo.class)
public abstract class MapperThree {
protected MapperTwo mapperTwo;
@Autowired
public final void setMapperTwo(MapperTwo mapperTwo) {
this.mapperTwo = mapperTwo;
}
UserDTO convert(@NonNull final LoginWrapper loginWrapper) {
final Login login = loginWrapper.getInstance();
return mapperTwo.convert(login);
}
}