英文:
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'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'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's say, hundreds of them. But they are pretty much the same.
My attempt doesn'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 = "longPrefixRequestId", source = "requestId")
@Mapping(target = "abcReason", source = "reason")
@Mapping(target = "defSubject", source = "subject")
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
乍一看,似乎你颠倒了target和source属性。在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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论