使用 mapstruct 映射带有参数的集合
Map a collection with parameter with mapstruct
要使用 mapstruct 映射某个对象,我需要一些自定义 post 处理,这需要一个额外的参数来完成它的工作:
@Mapper
public abstract class AlertConfigActionMapper {
@Mappings({ @Mapping(target = "label", ignore = true)})
public abstract AlertConfigActionTO map (AlertConfigAction action, Locale userLanguage);
@AfterMapping
public void setLabel (AlertConfigAction action, @MappingTarget AlertConfigActionTO to, Locale userLanguage) {
for (AlertConfigActionLabel label : action.getAlertConfigActionLabels()) {
if (label.getLanguage().equals(userLanguage)) {
to.setLabel(label.getLabel());
break;
} else if (label.getLanguage().equals(Locale.ENGLISH)) {
to.setLabel(label.getLabel());
}
}
}
}
这很好用。
当我向此映射器添加以下方法时,问题就开始了:
public abstract ArrayList<AlertConfigActionTO> mapList (List<AlertConfigAction> actions, Locale userLanguage);
我也需要传递此参数 (userLanguage),但在这种情况下 mapstruct 似乎 'break down':我为这部分生成了以下代码(这自然会产生编译错误):
@Override
public List<AlertConfigActionTO> mapList(List<AlertConfigAction> actions, Locale userLanguage) {
if ( actions == null && userLanguage == null ) {
return null;
}
List<AlertConfigActionTO> list = new List<AlertConfigActionTO>();
return list;
}
我确定它与参数有关,因为如果我将其删除(从所有映射方法中),则会正确生成 mapList 方法。
在这种情况下需要做什么才能允许自定义参数?
我认为这是不可能的。至少不是那样。问题是您准备了 interface/abstract class - 其余的由引擎完成。并且该引擎需要具有一个参数的方法......有装饰器,但它们以相同的方式进行。我会尝试注入语言。创建bean,将其标记为会话作用域,然后查找。对于 Spring,您将为此使用 ScopedProxyMode...不确定 CDI 的情况如何。
其他选项是更多的解决方法,然后是解决方案 - 也许 AlertConfigAction
可以传递该信息?
你所描述的是不可能的(还)。您可以在我们的 issue tracker 中打开功能请求吗?我们应该提供将参数表示为某种 "context" 的方法,它会向下传递到调用堆栈中。
作为暂时的解决方法,您可以考虑使用 ThreadLocal
,它是您在调用映射例程之前设置的,也是您在映射后自定义中访问的。这并不优雅 - 您需要确保清理本地线程以避免内存泄漏 - 但它应该可以解决问题。
我知道这个问题很老了,但我 运行 进入了这个问题,从 mapstruct 1.2 版开始,您可以使用 @Context
解决它
所以声明列表的映射需要像这样:
public abstract ArrayList<AlertConfigActionTO> mapList (List<AlertConfigAction> actions, @Context Locale userLanguage);
现在,您只需要像这样添加另一个非抽象映射:
public AlertConfigActionTO mapConcrete (AlertConfigAction action, @Context Locale userLanguage){
return map (action, userLanguage);
}
要使用 mapstruct 映射某个对象,我需要一些自定义 post 处理,这需要一个额外的参数来完成它的工作:
@Mapper
public abstract class AlertConfigActionMapper {
@Mappings({ @Mapping(target = "label", ignore = true)})
public abstract AlertConfigActionTO map (AlertConfigAction action, Locale userLanguage);
@AfterMapping
public void setLabel (AlertConfigAction action, @MappingTarget AlertConfigActionTO to, Locale userLanguage) {
for (AlertConfigActionLabel label : action.getAlertConfigActionLabels()) {
if (label.getLanguage().equals(userLanguage)) {
to.setLabel(label.getLabel());
break;
} else if (label.getLanguage().equals(Locale.ENGLISH)) {
to.setLabel(label.getLabel());
}
}
}
}
这很好用。 当我向此映射器添加以下方法时,问题就开始了:
public abstract ArrayList<AlertConfigActionTO> mapList (List<AlertConfigAction> actions, Locale userLanguage);
我也需要传递此参数 (userLanguage),但在这种情况下 mapstruct 似乎 'break down':我为这部分生成了以下代码(这自然会产生编译错误):
@Override
public List<AlertConfigActionTO> mapList(List<AlertConfigAction> actions, Locale userLanguage) {
if ( actions == null && userLanguage == null ) {
return null;
}
List<AlertConfigActionTO> list = new List<AlertConfigActionTO>();
return list;
}
我确定它与参数有关,因为如果我将其删除(从所有映射方法中),则会正确生成 mapList 方法。
在这种情况下需要做什么才能允许自定义参数?
我认为这是不可能的。至少不是那样。问题是您准备了 interface/abstract class - 其余的由引擎完成。并且该引擎需要具有一个参数的方法......有装饰器,但它们以相同的方式进行。我会尝试注入语言。创建bean,将其标记为会话作用域,然后查找。对于 Spring,您将为此使用 ScopedProxyMode...不确定 CDI 的情况如何。
其他选项是更多的解决方法,然后是解决方案 - 也许 AlertConfigAction
可以传递该信息?
你所描述的是不可能的(还)。您可以在我们的 issue tracker 中打开功能请求吗?我们应该提供将参数表示为某种 "context" 的方法,它会向下传递到调用堆栈中。
作为暂时的解决方法,您可以考虑使用 ThreadLocal
,它是您在调用映射例程之前设置的,也是您在映射后自定义中访问的。这并不优雅 - 您需要确保清理本地线程以避免内存泄漏 - 但它应该可以解决问题。
我知道这个问题很老了,但我 运行 进入了这个问题,从 mapstruct 1.2 版开始,您可以使用 @Context
解决它所以声明列表的映射需要像这样:
public abstract ArrayList<AlertConfigActionTO> mapList (List<AlertConfigAction> actions, @Context Locale userLanguage);
现在,您只需要像这样添加另一个非抽象映射:
public AlertConfigActionTO mapConcrete (AlertConfigAction action, @Context Locale userLanguage){
return map (action, userLanguage);
}