MapStruct映射不相关但相似的类

huangapple go评论78阅读模式
英文:

MapStruct map non-related similar classes

问题

我有许多不同包中具有相同名称类和相同属性的类假设每个类看起来像这样
```java
public class MiddlewareHeaderType {

    private String longPrefixRequestId;
    private String abcReason;
    private String defSubject;
}
com.mycompany.generated.ws.serviceA.MiddlewareHeader;
com.mycompany.generated.ws.serviceB.MiddlewareHeader;
com.mycompany.generated.ws.serviceC.MiddlewareHeader;
...

只要这些类是生成的(假设是从XSD生成的),我就无法更改它们。我想要一个通用对象,比如MySoapHeader,可以用作源数据,可转换为这些生成的类,使用MapStruct和Java 11(我不仅限于Java 8功能)。

public class MySoapHeader {

    private String requestId;
    private String reason;
    private String subject;
}

对于每个生成的头对象,我不太愿意创建单独的映射器类,因为假设有数百个。但它们基本上都是相同的。

我的尝试不能使用通用值,我还没有找到任何处理类似问题的答案:

@Named("base")
@Mapping(target = "longPrefixRequestId", source = "requestId")
@Mapping(target = "abcReason", source = "reason")
@Mapping(target = "defSubject", source = "subject")
<T> T base(MySoapHeader mySoapHeader);

@Mapping(target = "MiddlewareHeaderType", qualifiedByName = "base")
com.mycompany.generated.ws.serviceA.MiddlewareHeaderType serviceAHeader(MySoapHeader mySoapHeader);

@Mapping(target = "MiddlewareHeaderType", qualifiedByName = "base")
com.mycompany.generated.ws.serviceB.MiddlewareHeaderType serviceBHeader(MySoapHeader mySoapHeader);

@Mapping(target = "MiddlewareHeaderType", qualifiedByName = "base")
com.mycompany.generated.ws.serviceC.MiddlewareHeaderType serviceCHeader(MySoapHeader mySoapHeader);

<details>
<summary>英文:</summary>

I have a bunch of same-named classes with same attrubutes in various packages. Let&#39;s say each class looks like this:

public class MiddlewareHeaderType {

private String longPrefixRequestId;
private String abcReason;
private String defSubject;

}

com.mycompany.generated.ws.serviceA.MiddlewareHeader;
com.mycompany.generated.ws.serviceB.MiddlewareHeader;
com.mycompany.generated.ws.serviceC.MiddlewareHeader;
...

I am unable to change these as long as they are generated (let&#39;s say from a XSD). I want to have a generic object, say `MySoapHeader` to be used as a source data convertible into such generated classes using [MapStruct][1] and Java 11 (I am not limited to just Java 8 features).

public class MySoapHeader {

private String requestId;
private String reason;
private String subject;

}


I am reluctant to create a separate mapper class for each of the generated header object as long as there are, let&#39;s say, hundreds of them. But they are pretty much the same.

My attempt doesn&#39;t work with a generic value and I havent found anywhere an answer dealing with the similar problem:

@Named("base")
@Mapping(target = "longPrefixRequestId", source = "requestId")
@Mapping(target = "abcReason", source = "reason")
@Mapping(target = "defSubject", source = "subject")
<T> T base(MySoapHeader mySoapHeader);

@Mapping(target = "MiddlewareHeaderType", qualifiedByName = "base")
com.mycompany.generated.ws.serviceA.MiddlewareHeaderType serviceAHeader(MySoapHeader mySoapHeader);

@Mapping(target = "MiddlewareHeaderType", qualifiedByName = "base")
com.mycompany.generated.ws.serviceB.MiddlewareHeaderType serviceBHeader(MySoapHeader mySoapHeader);

@Mapping(target = "MiddlewareHeaderType", qualifiedByName = "base")
com.mycompany.generated.ws.serviceC.MiddlewareHeaderType serviceCHeader(MySoapHeader mySoapHeader);

    

  [1]: https://mapstruct.org/

</details>


# 答案1
**得分**: 3

你所寻找的是类似映射组合的内容。我们在1.4版中添加了这个功能(目前仍处于Beta测试阶段)。

通过这个功能,你可以定义自己的自定义映射注解。

例如:

```java
@Retention(RetentionPolicy.CLASS)
@Mapping(target = "longPrefixRequestId", source = "requestId")
@Mapping(target = "abcReason", source = "reason")
@Mapping(target = "defSubject", source = "subject")
public @interface SoapHeaderMapping { }

然后在你的映射器中可以这样使用:

@Mapper
public interface HeaderMapper {

    @SoapHeaderMapping
    com.mycompany.generated.ws.serviceA.MiddlewareHeaderType serviceAHeader(MySoapHeader mySoapHeader);

    @SoapHeaderMapping
    com.mycompany.generated.ws.serviceB.MiddlewareHeaderType serviceBHeader(MySoapHeader mySoapHeader);

    @SoapHeaderMapping
    com.mycompany.generated.ws.serviceC.MiddlewareHeaderType serviceCHeader(MySoapHeader mySoapHeader);

}

更多信息可以在这里找到。

英文:

What you are looking for is something like mapping composition. We have added this support in 1.4 (still in Beta now).

With this you can define your own custom mapping annotation.

e.g.

@Retention(RetentionPolicy.CLASS)
@Mapping(target = &quot;longPrefixRequestId&quot;, source = &quot;requestId&quot;)
@Mapping(target = &quot;abcReason&quot;, source = &quot;reason&quot;)
@Mapping(target = &quot;defSubject&quot;, source = &quot;subject&quot;)
public @interface SoapHeaderMapping { }

And then in your mapper you can do:

@Mapper
public interface HeaderMapper {

    @SoapHeaderMapping
    com.mycompany.generated.ws.serviceA.MiddlewareHeaderType serviceAHeader(MySoapHeader mySoapHeader);

    @SoapHeaderMapping
    com.mycompany.generated.ws.serviceB.MiddlewareHeaderType serviceBHeader(MySoapHeader mySoapHeader);

    @SoapHeaderMapping
    com.mycompany.generated.ws.serviceC.MiddlewareHeaderType serviceCHeader(MySoapHeader mySoapHeader);

}

More info can be found here

答案2

得分: 0

乍一看,似乎你颠倒了targetsource属性。在MySoapHeader.class中你有一个requestId,它是你基础方法的来源。

英文:

At first sight it seems that you have reversed target and source attributes. You have requestId in MySoapHeader.class which is the source for your base method.

huangapple
  • 本文由 发表于 2020年8月28日 19:20:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/63632797.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定