如何使用一个对象的多个属性并将其映射到另一个对象中的单个属性?

How to use multiple properties from an object and map it to a single one in an other?

我需要使用自定义映射和常规映射将两个对象映射在一起。有些属性是显式的,不需要任何修改,只需映射(因为它们没有相同的名称),但有些属性需要转换。

假设我有两个对象:

public class A {
    String id;
    String name;
    String firstname;
}

public class B {
    String nameB;
    String firstnameB;
}

还有一个接口:

@Mapper
public interface MyMapper {
    
    @Mappings({
        @Mapping(target="name", source="b.nameB"),
        @Mapping(target="firstname", source="b.firstnameB"),
        @Mapping(target="id", source="?", qualifiedByName="createId")
    })
    A BToA(B b);

    @Named("createId")
    default String createId(? ?) {

        return nameB + firstnameB;
    }
}

在此界面中,我想在自定义映射方法中将 A.id 映射到 B.nameB + B.firstnameB。我查看了 mapstruct 文档,但我无法弄清楚如何获取多个来源或仅将 B 对象作为来源。

这可能吗?如果不能,我该如何实现?

方案一:Method qualifier

@Mapper
public interface MyMapper {

    @Mappings({
            @Mapping(target="name", source="bObject.nameB"),
            @Mapping(target="firstname", source="bObject.firstnameB"),
            @Mapping(target="id", source="bObject", qualifiedByName="createId")
    })
    A BToA(B bObject);

    @Named("createId")
    default String createId(B bObject) {
        return bObject.nameB + bObject.firstnameB;
    }
}

生成的代码:

public class MyMapperImpl implements MyMapper {
    @Override
    public A BToA(B bObject) {
        if ( bObject == null ) {
            return null;
        }
        A a = new A();
        a.name = bObject.nameB;
        a.firstname = bObject.firstnameB;
        a.id = createId( bObject );
        return a;
    }
}

方案二:Expression

@Mapper
public interface MyMapper {
    @Mappings({
            @Mapping(target="name", source="bObject.nameB"),
            @Mapping(target="firstname", source="bObject.firstnameB"),
            @Mapping(target="id", expression = "java(bObject.nameB + bObject.firstnameB)")
    })
    A BToA(B bObject);
}

生成的代码:

public class MyMapperImpl implements MyMapper {
    @Override
    public A BToA(B bObject) {
        if ( bObject == null ) {
            return null;
        }
        A a = new A();
        a.name = bObject.nameB;
        a.firstname = bObject.firstnameB;
        a.id = bObject.nameB + bObject.firstnameB;
        return a;
    }
}

方案三:AfterMapping annotation

@Mapper
public interface MyMapper {
    @Mappings({
            @Mapping(target="name", source="bObject.nameB"),
            @Mapping(target="firstname", source="bObject.firstnameB"),
    })
    A BToA(B bObject);

    @AfterMapping
    default void afterMapping(@MappingTarget A aObject, B bObject) {
        aObject.id = bObject.nameB + bObject.firstnameB;
    }
}

生成的代码:

public class MyMapperImpl implements MyMapper {
    @Override
    public A BToA(B bObject) {
        if ( bObject == null ) {
            return null;
        }
        A a = new A();
        a.name = bObject.nameB;
        a.firstname = bObject.firstnameB;
        afterMapping( a, bObject );
        return a;
    }
}