提问者:小点点

如何使用MapStruct从JaxbElement<X>映射到JaxbElement<Y>


我本打算在github上创建一个问题,但问题模板说我宁愿先在这里讨论它,所以我们开始:

我试图使用Mapstruct从一个WSDL生成的实体集生成映射到另一个。然而,如果不添加“默认”方法(手动映射),它就不起作用!这似乎很奇怪,因为我希望这种映射对Mapstruct来说应该不难。重现案例在这里:https://github.com/62mkv/wsdl-mapstruct-repro-case

代码的要点在这里:

@Mapper(uses = {
    org.system.wsdl.legacy.ObjectFactory.class
})
public interface WsMapper {

org.system.wsdl.legacy.SellGarlicRequest fromCloud(org.system.wsdl.cloud.SellGarlicRequest request);

}

上面的这段代码将无法编译,并带有以下消息:

不能将属性"javax. xml.bind.JAXBElement inputParameters"映射到"javax.xml.bind.JAXBElement inputParameters"。考虑声明/实现一个映射方法:"javax.xml.bind.JAXBElement map(javax.xml.bind.JAXBElement value)"。org.system.wsdl.legacy.SellGarlicRequest fromCloud(org.system.wsdl.cloudSellGarlicRequest);

基本上,映射将如下所示:EntityNew-

正如我在这里读到的(https://stackoverflow.com/a/46015381/2583044),从JaxbElement到T的映射对于MapStruct来说是微不足道的,要从T映射到JaxbElement,必须使用“使用”注释并提供ObjectFactory. class,我这样做了;然而…这似乎还不够。

如果我添加这两个方法,代码编译良好:

org.system.wsdl.legacy.GarlicParameterCollection garlicParameterCollectionToGarlicParameterCollection(org.system.wsdl.cloud.GarlicParameterCollection collection);

default JAXBElement<org.system.wsdl.legacy.GarlicParameterCollection> garlicParameterCollectionToGarlicParameterCollection(JAXBElement<org.system.wsdl.cloud.GarlicParameterCollection> parameterCollectionJAXBElement) {
    return new org.system.wsdl.legacy.ObjectFactory().createSellGarlicRequestInputParameters(
            this.garlicParameterCollectionToGarlicParameterCollection(parameterCollectionJAXBElement.getValue())
    );
}

这是mapstruct中的潜在问题,还是我只是不知道如何做好它?


共1个答案

匿名用户

问题是MapStruct将您的对象工厂方法(带有参数)视为映射方法。因此,它提供了一个目标,但它也有一个源。如果您意识到这一点,那么映射突然变得不对称(就像它最初出现的那样)。

简单的解决方案是指导MapStruct如何处理此问题。

所以:试试这个:


@Mapper(uses = {
        org.system.wsdl.legacy.ObjectFactory.class
})
public interface WsMapper {

    org.system.wsdl.legacy.GarlicParameterCollection garlicParameterCollectionToGarlicParameterCollection(org.system.wsdl.cloud.GarlicParameterCollection collection);

    @Mapping( target = "inputParameters", source = "inputParameters.value") // this instructs MapStruct to use value of the source JAXBElement (for which it has an object factory method) instead of trying to map JAXBElement to JAXBElement.
    org.system.wsdl.legacy.SellGarlicRequest fromCloud(org.system.wsdl.cloud.SellGarlicRequest request);

}

最后但并非最不重要的一点是,您需要定义第一个方法garlicParameterCollection ToGarlicParameterCollection最初让我感到惊讶。

原因:MapStruct要么尝试:1.找到一个映射方法(如果你忽略这个方法,它就不存在),要么2.尝试生成一个直接映射(通过检查它是否可以找到源和目标上所有属性的方法)。

然而,MapStruct找不到这种映射的直接案例(原则上它需要在其路径上应用所有其他可能的映射(例如对象工厂中的所有方法),然后尝试生成一个映射方法,如2中所述,这可能是很多组合。这种功能不存在(我想也是负载密集型的)。