我们使用
immutables framework生成所有DTO.现在我们想用
mapstruct将这些对象映射到另一个.但生成的DTO是不可变的,没有setter,也没有构造函数,对应于builder模式.它们仅通过静态builder() – 方法访问的相应构建器填充.
我们试图将DTO1映射到DTO2.Builder,如果mapstruct能识别Builder中的setter但这些没有void返回类型但返回Builder本身以进行流畅的连接,那么它将起作用.
所以这是示例的代码.
我们有两个接口
@Value.Immutable
public interface MammalDto {
public Integer getNumberOfLegs();
public Long getNumberOfStomachs();
}
和
@Value.Immutable
public interface MammalEntity {
public Long getNumberOfLegs();
public Long getNumberOfStomachs();
}
然后我们有了maptruct的Mapper接口:
@Mapper(uses = ObjectFactory.class)
public interface SourceTargetMapper {
SourceTargetMapper MAPPER = Mappers.getMapper( SourceTargetMapper.class );
ImmutableMammalEntity.Builder toTarget(MammalDto source);
}
要使mapORG找到Builder,我们需要一个Factory:
public class ObjectFactory {
public ImmutableMammalDto.Builder createMammalDto() {
return ImmutableMammalDto.builder();
}
public ImmutableMammalEntity.Builder createMammalEntity() {
return ImmutableMammalEntity.builder();
}
}
为了生成代码,编译器插件被指示使用两个注释处理器:
org.apache.maven.plugins
maven-compiler-plugin
3.6.1
1.8
1.8
org.immutables
value
2.2.8
org.mapstruct
mapstruct-processor
1.2.0.Beta3
注意:这仅适用于mapstruct版本> 1.2.x.旧版本在干净构建(mvn clean compile)中存在问题,即它们找不到不可变构建的源.在第二个构建(没有干净)中,他们会找到immutables实现,因为它们在注释处理器运行之前位于类路径中.这个bug现在已修复.
这就像一个魅力.首先生成interfactes的Immutable实现,并且mapstruct使用它们来生成构建器.
但测试表明没有设置属性:
@Test
public void test() {
MammalDto s = ImmutableMammalDto.builder().numberOfLegs(4).numberOfStomachs(3l).build();
MammalEntity t = SourceTargetMapper.MAPPER.toTarget(s).build();
assertThat(t.getNumberOfLegs()).isEqualTo(4);
assertThat(t.getNumberOfStomachs()).isEqualTo(3);
}
断言失败.一看maptruct生成的mapper就会发现它显然没有找到任何setter:
@Generated(
value = "org.mapstruct.ap.MappingProcessor",//...
)
public class SourceTargetMapperImpl implements SourceTargetMapper {
private final ObjectFactory objectFactory = new ObjectFactory();
@Override
public Builder toTarget(MammalDto source) {
if ( source == null ) {
return null;
}
Builder builder = objectFactory.createMammalEntity();
return builder;
}
}
返回空构建器.我认为原因是生成的构建器的setter实现,因为它返回自身以创建一个流畅的API:
public final Builder numberOfLegs(Long numberOfLegs) {
this.numberOfLegs = Objects.requireNonNull(numberOfLegs,"numberOfLegs");
return this;
}
有没有办法让mapstruct找到这些setter?或者甚至是用构建器处理这些不可变对象的更好方法?
编辑:正如我在评论中所说,我遇到了Issue #782.在版本1.2.0.Beta3建设者仍然不支持.但是关于这个主题有几个讨论,所以如果一个人遇到同样的问题,可能会有兴趣.