#java #mapstruct
#java #mapstruct
Вопрос:
Я пытаюсь выяснить, как реализовать следующее сопоставление:
class SuperComplexClass {
Long value;
String description;
}
class MapIntoMe {
// Many other fields that is also mapped
SuperComplexClass superComplexObject;
}
class MapFromMe {
ComplexClassPart1 complexClassPart;
}
class AdditionalData {
ComplexClassPart2 complexClassPart;
}
@Mapper
public interface SomeFancyMapper {
@Mapping(target = "superComplexObject", source = "{mfm.complexPart, ad.complexPart}",
qualifiedByName = "mapSuperComplexObject")
MapIntoMe mapFromMeIntoMe(MapFromMe mfm, AdditionalData ad);
@Named("mapSuperComplexObject")
default SuperComplexClass mapSuperComplexObject(ComplexPart1 p1, ComplexPart2 p2) {
SuperComplexClass superObject = new SuperComplexClass();
//some logic that calculates and fills superObject]
return superObject;
}
}
И теперь, очевидно, выражение like source = "{mfm.complexPart, ad.complexPart}"
не работает, но оно ясно показывает, чего я хотел бы достичь.
До сих пор я не смог найти ответ, если это возможно при таком подходе и без каких-либо уродливых обходных путей.
Есть идеи?
Ответ №1:
В настоящее время не поддерживается повторное использование методов сопоставления с более чем одним параметром. Вот почему что-то вроде выражения, которым вы поделились, не работает.
Однако вы можете использовать expression
, @AfterMapping
или @Context
(в случае, если вам не нужно использовать AdditionalData
для другого сопоставления) для достижения того, что вам нужно.
Использование выражения
@Mapper
public interface SomeFancyMapper {
@Mapping(target = "superComplexObject", expression = "java(mapSuperComplexObject(mfm.getComplexPart(), ad.getComplexPart()))")
MapIntoMe mapFromMeIntoMe(MapFromMe mfm, AdditionalData ad);
default SuperComplexClass mapSuperComplexObject(ComplexPart1 p1, ComplexPart2 p2) {
SuperComplexClass superObject = new SuperComplexClass();
//some logic that calculates and fills superObject]
return superObject;
}
}
Использование @AfterMapping
@Mapper
public interface SomeFancyMapper {
@Mapping(target = "superComplexObject", ignore = true)
MapIntoMe mapFromMeIntoMe(MapFromMe mfm, AdditionalData ad);
@AfterMapping
default void mapSuperComplexObject(@MappingTarget MapIntoMe target, MapFromMe mfm, AdditionalData ad) {
SuperComplexClass superObject = new SuperComplexClass();
//some logic that calculates and fills superObject]
return superObject;
}
}
Использование @Context
@Mapper
public interface SomeFancyMapper {
@Mapping(target = "superComplexObject", source = "complexPart",
qualifiedByName = "mapSuperComplexObject")
MapIntoMe mapFromMeIntoMe(MapFromMe mfm, @Context AdditionalData ad);
@Named("mapSuperComplexObject")
default SuperComplexClass mapSuperComplexObject(ComplexPart1 p1, @Context AdditionalData ad) {
SuperComplexClass superObject = new SuperComplexClass();
//some logic that calculates and fills superObject]
return superObject;
}
}
Имейте в виду, что при использовании @Context
параметра, аннотированного этой аннотацией, его нельзя использовать Mapping#target
. Это дополнительный контекст, который может быть передан другим методам отображения или методам жизненного цикла.