【问题标题】:MapStruct: How to do an @AfterMapping with optional parameters?MapStruct:如何使用可选参数进行@AfterMapping?
【发布时间】:2019-07-22 23:16:08
【问题描述】:

我创建了一个抽象映射器类,它具有以下方法:

public abstract Dest mapSourceToDest(Source source);
public abstract Dest mapSourceToDestWithParams(Source source, @Context Param1 param1; @Context Param2 param2);

Source 中有两个成员在转换为Dest 时非常昂贵(就性能而言)。
上面提到的第一种方法应该在source的所有成员都应该转换时使用(包括两次昂贵的转换)。
第二种方法应该在转换结果时使用在从sourcedest 的转换完成之前,这两个“昂贵”的成员就已经知道了。在这种情况下,这两个成员的转换结果作为参数param1param2 传递。这些参数应该用于避免昂贵的转换。
两个成员的转换是在一个用@AfterMapping注解的方法中完成的。我在AfterMapping方法中基本上想做的事情如下:

  • 如果没有提供这两个参数,则进行昂贵的转换
  • 如果提供了这两个参数,请使用它们并且不要进行转换

基本上应该是这样的:

@AfterMapping
protected void setExpensiveParams(Source source, @MappingTarget Dest dest, 
                                   @Context Param1 param1, @Context Param2 param2) {
    if (param1 == null || param2 == null) {
        performExpensiveConversionForParam1AndParam2();
    } else {
       dest.setParam1(param1);
       dest.setParam2(param2); 
    } 
}

这在这两种情况下都不起作用,因为这个 AfterMapping 方法只有在提供了带有 @Context 注释的两个参数时才会被调用。正如 MapStruct 文档明确指出的那样,这些上下文参数可能不为空,这与预期的一样。

我想不出一种方法来执行这两种替代类型的 AfterMappings,这取决于一个映射器类中可选参数的存在。我现在的解决方法是使用两个映射器类。不过,我真的很想用一个映射器类来处理这个问题。

【问题讨论】:

  • 有几种方法可以做到这一点。

标签: java mapstruct


【解决方案1】:

我看到了 2 个选项。

选项 1: * 您可以使用属性 Param1 和 Param2 创建您自己的上下文类,您可以使用 Param1 和 Param2(优化)构造或不使用它们。此上下文仅传递给一个方法。 MapStruct 的一个鲜为人知的特性是您可以将生命周期方法(@AfterMapping)放入上下文中的方法中。根据是否设置了参数,您可以从映射器中的上下文调用昂贵的映射或在上下文中实现它们

选项 2: 使用 @MappingTarget 并使用已经设置的两个目标参数预先创建目标对象。取消相应的来源。使用 nullvaluepropertymappingstrategy .ignore 以便 MapStruct 在相应的源属性为空时跳过这些。您甚至可以使用第二种方法的签名在默认方法中实现这一点。

【讨论】:

  • 出于好奇..您选择了哪个选项?
猜你喜欢
  • 2022-11-19
  • 2019-05-10
  • 1970-01-01
  • 1970-01-01
  • 2015-11-14
  • 1970-01-01
  • 2012-04-14
  • 1970-01-01
  • 2021-02-27
相关资源
最近更新 更多