我們使用immutables framework來生成所有DTO。現在我們想用mapstruct將這些對象映射到另一個。但生成的DTO是不可變的,並且沒有setter,也沒有構造器,對應於構建器模式。它們只能通過由靜態builder()
-方法訪問的相應構建器填充。使用構建器(使用immutables註釋處理器)將映射對象映射到不可變對象映射
我們試着將DTO1映射到DTO2.Builder,它可以工作,如果地圖可以識別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();
}
然後我們有mapstruct映射器接口:
@Mapper(uses = ObjectFactory.class)
public interface SourceTargetMapper {
SourceTargetMapper MAPPER = Mappers.getMapper(SourceTargetMapper.class);
ImmutableMammalEntity.Builder toTarget(MammalDto source);
}
對於mapstruct找到我們需要一個工廠的生成器:
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
)中存在問題,即他們沒有找到剛建立的不可變源。在第二個版本(沒有清理)中,他們會發現不可變的實現,因爲它們在運行註釋處理器之前處於類路徑中。這個bug現在已經修復。
這工作就像一個魅力。首先生成接口的不可變實現,地圖使用它們生成構建器。
但測試表明,沒有屬性被設置:
@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);
}
的斷言失敗。在由mapstruct產生映射器一看就表明,它顯然沒有發現任何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;
}
}
空建設者。我想原因是二傳手實施產生的建設者,因爲它返回自己創建一個流暢的API:
public final Builder numberOfLegs(Long numberOfLegs) {
this.numberOfLegs = Objects.requireNonNull(numberOfLegs, "numberOfLegs");
return this;
}
有沒有辦法讓mapstruct找到這些制定者?或者甚至有更好的方式來與建設者打交道這樣的不可變對象?
編輯:正如我在評論中指出的,我碰到了Issue #782。在版本1.2.0中.Beta3構建器仍然不受支持。但是有幾個關於這個話題的討論,所以如果一個人有同樣的問題,可能會很有趣。
如前所述由Andreas孤店我遇到了一個已知的問題定義這些設置。功能請求#782「不可變對象與構建器的映射」從版本1.1.0.Beta2開始。一個expample可以在mapstruct的集成測試模塊中找到。我將在下一次迭代中將這個例子適應於特定的需求。歡迎具體實施的任何建議。 Java-Model-API似乎有點棘手...... –