指定将由MapStruct用于隐式映射的对象名称。

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

Specify the name of the object that will be used for implicit mapping by MapStruct

问题

@Mapping(target = "ca1", source = "a.ca1")
@Mapping(target = "ca2", source = "a.ca2")
C mapFrom(A a, B b);

我想要在MapStruct中明确指定哪个对象将用于参数中传递的对象进行隐式映射,我有以下示例:

@Mapping(target = "ca1", source = "a.ca1")
@Mapping(target = "ca2", source = "a.ca2")
C mapFrom(A a, B b);

我想要使用A进行显式映射,B用于所有隐式映射,问题是A和B具有许多具有相同名称的属性,它们之间会发生冲突。我尝试使用

@Mapping(target = ".", source = "b")

但这并不能解决问题,我仍然收到"java: Several possible source properties for target property..."错误。另外,使用`@BeanMapping(ignoreByDefault = true)` 将会很困难,因为我将不得不手动编写很多映射。如果我们能够指定用于隐式映射的对象将非常方便,有什么帮助吗?(我正在使用版本1.5.2)

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

I would like to know if it&#39;s possible in MapStruct to specify explicitly what is the object that will be used for implicit mapping among the ones passed in argument to the mapper, I have the following example :

@Mapping(target = "ca1", source = "a.ca1")
@Mapping(target = "ca2", source = "a.ca2")
C mapFrom(A a, B b);

I want to use A for explicit mapping and B for all implicit mapping, the issue is that A and B have a lot of properties with same name that conflicts together, I tried to use 

@Mapping(target = ".", source = "b")

but that does not solve the issue, I still get java: Several possible source properties for target property... Error, also using the ```@BeanMapping(ignoreByDefault = true)``` will make it very difficult as I will have to wirte by hand a lot of mappings. I think it will be very handy if we could specify the object that will be used for implicit mapping, any help ? (I am using version 1.5.2)

</details>


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

根据[MapStruct文档][1]的说明:

> 如果多个源对象定义具有相同名称的属性,则必须使用@Mapping注释指定要检索属性的源参数,如示例中所示的描述属性。如果不解决此类模糊性,则将引发错误。

但是,可以通过以下3种方法的下一个解决方案来实现所需的功能:

```java
@Mapper
public interface TestMapper {

    TestMapper INSTANCE = Mappers.getMapper(TestMapper.class);

    default ResultClass combineOrdered(ImplicitClass implicitClass, ExplicitClass explicitClass) {
        ResultClass resultClass = populateImplicitly(implicitClass);
        populateExplicitly(resultClass, explicitClass);
        return resultClass;
    }

    ResultClass populateImplicitly(ImplicitClass implicitClass);

    @BeanMapping(ignoreByDefault = true)
    @Mapping(source = "explicitClass.explicitField", target = "explicitField")
    void populateExplicitly(@MappingTarget ResultClass resultClass, ExplicitClass explicitClass);
}

MapStruct将生成populateImplicitly方法的代码,从ImplicitClass中隐式填充所有字段,以及populateExplicitly方法的代码,仅显式填充来自ExplicitClass的声明字段。

这两种方法可以使用额外的combineOrdered方法组合在一起,首先调用隐式映射(以填充所有字段),然后只填充显式字段。

使用combineOrdered方法应该有助于实现您所需的功能。

英文:

According to MapStruct documentation:

> In case several source objects define a property with the same name,
> the source parameter from which to retrieve the property must be
> specified using the @Mapping annotation as shown for the description
> property in the example. An error will be raised when such an
> ambiguity is not resolved.

However, needed functionality could be achieved with a next workaround of 3 methods:

@Mapper
public interface TestMapper {

    TestMapper INSTANCE = Mappers.getMapper(TestMapper.class);

    default ResultClass combineOrdered(ImplicitClass implicitClass, ExplicitClass explicitClass) {
        ResultClass resultClass = populateImplicitly(implicitClass);
        populateExplicitly(resultClass, explicitClass);
        return resultClass;
    }

    ResultClass populateImplicitly(ImplicitClass implicitClass);

    @BeanMapping(ignoreByDefault = true)
    @Mapping(source = &quot;explicitClass.explicitField&quot;, target = &quot;explicitField&quot;)
    void populateExplicitly(@MappingTarget ResultClass resultClass, ExplicitClass explicitClass);
}

MapStruct will generate code for populateImplicitly method to implicitly populate all fields from ImplicitClass - and code for populateExplicitly method to explicitly populate only declared fields from ExplicitClass.

And those 2 approaches could be combined using additional method combineOrdered - which will first call implicit mappings (to populate all the fields) - and then will populate only explicit fields.

Usage of such combineOrdered method should help to do what you're looking for.

huangapple
  • 本文由 发表于 2023年3月15日 19:46:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/75744266.html
匿名

发表评论

匿名网友

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

确定