英文:
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}"
这样的表达式是不起作用的,但它清楚地显示了我想要实现的内容。
到目前为止,我无法找到答案,是否可以通过这种方法实现,而不需要一些丑陋的变通方法。
有什么想法吗?
英文:
I am trying to figure out how to implement the following mapping:
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;
}
}
And now obviously expression like source = "{mfm.complexPart, ad.complexPart}"
is not working, but it shows clearly what I would like to achieve.
So far I wasn't able to find the answer if that's possible with this approach and without some ugly workarounds.
Any ideas?
答案1
得分: 5
目前不支持重用带有多个参数的映射方法。这就是为什么类似于您分享的表达式不起作用的原因。
但是,您可以使用 expression
、@AfterMapping
或者 @Context
(如果您不需要在其他映射中使用 AdditionalData
)来实现您需要的功能。
使用 Expression
@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
target.setSuperComplexObject(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
中使用。它是一个附加的上下文,可以传递给其他映射方法或生命周期方法。
英文:
Currently it is not supported to reuse mapping methods with more than one parameter. That is why something like the expression you shared doesn't work.
However, you could use expression
, @AfterMapping
or @Context
(in case you don't need to use AdditionalData
for other mapping) to achieve what you need.
Using Expression
@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;
}
}
Using @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;
}
}
Using @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;
}
}
Keep in mind that when using @Context
the parameter annotated with that annotation cannot be used in Mapping#target
. It is an additional context that can be passed to other mapping methods or lifecycle methods.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论