使用mapstruct,我需要的是一个具有多个源的映射方法,并且这几个源被传递给其他映射方法,这样我就可以为需要这些附加源的所有映射方法提供所有多个源。
目前有两个功能可以一起工作:
因此,功能需求是要么允许辅助源参数传递给其他映射方法,要么使 @Context 参数能够被或@Mapping(target="something", source="ctx.somethingElse")引用@Mapping(target="ctx.something", source="somethingElse)
例子 :
// source classes : `Instant timestamp` is a field I obtain separately
Instant timestamp;
class WrapperSource
List<NestedSource> nested;
class NestedSource
String name;
// target classes : I want to map the nested and name field but also to insert the timestamp in both the WrapperTarget and every NestedTarget in the nested list
class WrapperTarget
Instant timestamp;
List<NestedTarget> nested;
class NestedTarget
String name;
Instant timestamp;
Run Code Online (Sandbox Code Playgroud)
理想情况下,映射类似于:
// Currently this doesn't work because we can't reference the @Context in the source attribute
@Mapping(target = "nested", source="source.nested")
@Mapping(target = "timestamp", source="timestamp")
WrapperTarget map(WrapperSource source, @Context Instant timestamp);
@Mapping(target = "name", source="source.name")
@Mapping(target = "timestamp", source="timestamp")
NestedTarget map(NestedSource source, @Context Instant timestamp);
Run Code Online (Sandbox Code Playgroud)
或者 :
// Currently this doesn't work because the second method with 2 sources in not called by the first generated method
@Mapping(target = "nested", source="source.nested")
@Mapping(target = "timestamp", source="timestamp")
WrapperTarget map(WrapperSource source, Instant timestamp);
@Mapping(target = "name", source="source.name")
@Mapping(target = "timestamp", source="timestamp")
NestedTarget map(NestedSource source, Instant timestamp);
Run Code Online (Sandbox Code Playgroud)
对我有用的唯一(详细)解决方法是:
// @Context is passed around and I can manually use it as a source in an @AfterMapping but it requires additional code
WrapperTarget map(WrapperSource source, @Context Instant timestamp);
@AfterMapping
void map(WrapperSource source, @MappingTarget WrapperTarget target, @Context Instant timestamp) {
target.setTimestamp(timestamp);
}
NestedTarget map(NestedSource source, @Context Instant timestamp);
@AfterMapping
void map(NestedSource source, @MappingTarget NestedTarget target, @Context Instant timestamp) {
target.setTimestamp(timestamp);
}
Run Code Online (Sandbox Code Playgroud)
这可以正常工作,但需要额外的手动代码,因此更好的替代方案是能够@Context在@Mapping's attributes. 这样我就可以使用第一个“理想”映射示例。
对于这个问题有更好的解决方法吗?
@Context应该是参数所暗示的内容。映射的上下文信息,因此不参与映射本身。映射原则上是从源到目标。
请记住:MapStruct 可以解决很多问题,但它永远无法解决所有问题。
但是:你可以尝试这个:
class WrapperTarget implements TimeStamped
Instant timestamp;
List<NestedTarget> nested;
class NestedTarget implements TimeStamped
String name;
Instance timestamp;
interface TimeStamped{
void setTimestamp(Instance timeStamp);
}
Run Code Online (Sandbox Code Playgroud)
定义您自己的上下文... MapStruct 在您定义的上下文上自动调用后映射。您可以在这样的上下文中放置更多内容,例如在映射之前解析存储库中的内容、id...等。
class MyContext {
Instance timestamp;
@AfterMapping
map(@MappingTarget TimeStamped timeStamped)
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您的映射与上下文保持干净。当然,您需要在调用该方法之前初始化上下文。也许您可以在上下文的构造中构造时间点(如果要求是在各处都包含相同的时间点)。
@Mapping(target = "nested", source="source.nested")
WrapperTarget map(WrapperSource source, @Context MyContext ctx);
@Mapping(target = "name", source="source.name")
NestedTarget map(NestedSource source, @Context MyContext ctx);
Run Code Online (Sandbox Code Playgroud)
对于上下文的使用,您可以查看此示例。
| 归档时间: |
|
| 查看次数: |
4546 次 |
| 最近记录: |