我们试图将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(); } }
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.6.1</version> <configuration> <source>1.8</source> <target>1.8</target> <annotationProcessorPaths> <path> <groupId>org.immutables</groupId> <artifactId>value</artifactId> <version>2.2.8</version> </path> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.2.0.Beta3</version> </path> </annotationProcessorPaths> </configuration> </plugin>
注意:这仅适用于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?或者甚至是用构建器处理这些不可变对象的更好方法?
编辑:正如我在评论中所说,我遇到了@L_403_2@.在版本1.2.0.Beta3建设者仍然不支持.但是关于这个主题有几个讨论,所以如果一个人遇到同样的问题,可能会有兴趣.
解决方法
作为解决方法,我们一直在使用不可变dto的可修改实现.
你也可以尝试一下.直接使用构建器和对象工厂更好.
@ Value.Modifiable使用setter生成实现.
@ Value.Style(create =“new”)生成public no args构造函数.
@Value.Immutable @Value.Modifiable @Value.Style(create = "new") public interface MammalEntity { public Long getNumberOfLegs(); public Long getNumberOfStomachs(); }
那么你的映射器将更简单,不需要在对象工厂中.
@Mapper public interface SourceTargetMapper { ModifiableMammalEntity toTarget(MammalDto source); }
在这种情况下,MapStruct可以在ModifiableMammalEntity中看到setter
这种映射器的用法看起来像
// Here you don't need to worry about implementation of MammalEntity is. The interface `MammalEntity` is immutable. MammalEntity mammalEntity = sourceTargetMapper.toTarget(source);