MapStruct - 基于 2 个或更多不同源对象的目标字段的自定义映射
MapStruct - custom mapping of target field based on 2 or more different source objects
我正在尝试弄清楚如何实现以下映射:
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;
}
}
现在显然像 source = "{mfm.complexPart, ad.complexPart}"
这样的表达式不起作用,但它清楚地表明了我想要实现的目标。
到目前为止,如果没有一些丑陋的解决方法,我无法找到答案(如果可以的话)。
有什么想法吗?
目前不支持重复使用具有多个参数的映射方法。这就是为什么像您分享的表情这样的东西不起作用的原因。
但是,您可以使用 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
中使用。它是一个额外的上下文,可以传递给其他映射方法或生命周期方法。
我正在尝试弄清楚如何实现以下映射:
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;
}
}
现在显然像 source = "{mfm.complexPart, ad.complexPart}"
这样的表达式不起作用,但它清楚地表明了我想要实现的目标。
到目前为止,如果没有一些丑陋的解决方法,我无法找到答案(如果可以的话)。
有什么想法吗?
目前不支持重复使用具有多个参数的映射方法。这就是为什么像您分享的表情这样的东西不起作用的原因。
但是,您可以使用 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
中使用。它是一个额外的上下文,可以传递给其他映射方法或生命周期方法。