MapStruct:如何使用可选参数执行@AfterMapping?
MapStruct: How to do an @AfterMapping with optional parameters?
我创建了一个抽象映射器 class,它具有以下方法:
public abstract Dest mapSourceToDest(Source source);
public abstract Dest mapSourceToDestWithParams(Source source, @Context Param1 param1; @Context Param2 param2);
Source
中有两个成员,在转换为 Dest
时转换成本非常高(就性能而言)。
source
的所有成员都需要进行转换(包括两次昂贵的转换)时应该使用上述第一种方法。
结果应该使用第二种方法在完成从 source
到 dest
的转换之前,已经知道两个 "expensive" 成员的转换。在本例中,这两个成员的转换结果作为参数 param1
和 param2
传递。这些参数应该用于避免昂贵的转换。
两个成员的转换是在一个用@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 文档清楚地指出像这样的上下文参数可能不为空。
我想不出一种方法来执行这两种替代类型的 AfterMapping,这取决于一个映射器中可选参数的存在 class。我现在的解决方法是使用两个映射器 classes。不过,我真的很想用一个映射器 class 来处理这个问题。
我看到了 2 个选项。
选项 1:
* 您可以使用属性 Param1 和 Param2 创建自己的上下文 class,您可以使用 Param1 和 Param2(优化)或不使用这些属性来构造它们。此上下文仅传递给一个方法。 MapStruct 的一个鲜为人知的特性是您可以将生命周期方法 ( @AfterMapping ) 放在上下文中的方法中。根据是否设置了参数,您可以从映射器的上下文中调用昂贵的映射或在上下文中实现它们
选项 2:
使用 @MappingTarget 并使用已经设置的两个目标参数预先创建目标对象。使相应的来源无效。使用 nullvaluepropertymappingstrategy .ignore 以便 MapStruct 在相应的源属性为空时跳过这些。您甚至可以使用第二个方法的签名在默认方法中实现它。
我创建了一个抽象映射器 class,它具有以下方法:
public abstract Dest mapSourceToDest(Source source);
public abstract Dest mapSourceToDestWithParams(Source source, @Context Param1 param1; @Context Param2 param2);
Source
中有两个成员,在转换为 Dest
时转换成本非常高(就性能而言)。
source
的所有成员都需要进行转换(包括两次昂贵的转换)时应该使用上述第一种方法。
结果应该使用第二种方法在完成从 source
到 dest
的转换之前,已经知道两个 "expensive" 成员的转换。在本例中,这两个成员的转换结果作为参数 param1
和 param2
传递。这些参数应该用于避免昂贵的转换。
两个成员的转换是在一个用@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 文档清楚地指出像这样的上下文参数可能不为空。
我想不出一种方法来执行这两种替代类型的 AfterMapping,这取决于一个映射器中可选参数的存在 class。我现在的解决方法是使用两个映射器 classes。不过,我真的很想用一个映射器 class 来处理这个问题。
我看到了 2 个选项。
选项 1: * 您可以使用属性 Param1 和 Param2 创建自己的上下文 class,您可以使用 Param1 和 Param2(优化)或不使用这些属性来构造它们。此上下文仅传递给一个方法。 MapStruct 的一个鲜为人知的特性是您可以将生命周期方法 ( @AfterMapping ) 放在上下文中的方法中。根据是否设置了参数,您可以从映射器的上下文中调用昂贵的映射或在上下文中实现它们
选项 2: 使用 @MappingTarget 并使用已经设置的两个目标参数预先创建目标对象。使相应的来源无效。使用 nullvaluepropertymappingstrategy .ignore 以便 MapStruct 在相应的源属性为空时跳过这些。您甚至可以使用第二个方法的签名在默认方法中实现它。