不同字段名称的 orika customMap 的反射

reflection for orika customMap of different fieldNames

假设我们有 2 个 DTO:

public class ClassA {
    private String elementAClassA;
    private String elementBClassA;
    private Integer elementCClassA;
}

public class ClassB {
    private String elementAClassB;
    private String elementBClassB;
    private Integer elementCClassB;
}

如何使用通用代码(或 reflection/customised)映射这些 DTO,即不简单地使用:

MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        mapperFactory.classMap(ClassA.class, ClassB.class)
                .field("elementAClassA", "elementAClassB")
                .field("elementBClassA", "elementBClassB")
                .field("elementCClassA", "elementCClassB").register();

如果您询问如何将公共属性从一种表示形式 (ClassA) 映射到另一种表示形式 (ClassB),您可以使用 byDefault(),如 documentation 所示。

mapperFactory.classMap(BasicPerson.class, BasicPersonDto.class)
    .field("name", "fullName")
    .field("age", "currentAge")
    .byDefault()
    .register();

根据您的示例,不清楚类型是否不同或两个表示之间的名称是否不同(它不可读为 Java)。反射只有在字段命名相同时才有用,在这种情况下你应该只使用 byDefault(),或者如果它们是相同的类型并且你在每种表示中只有一种类型,你可以做一个自动装配式映射;但你会做出各种你不想做出的假设。

I found the solution and hope will help others.
Steps are as below:

1. Overide newClassMapBuilder of Factory class.
2. fetch fields of both classes using Field reflection. 
3. map new field to build, if elementName matched.
4. Then, create factory and pass this overiden class.

-- Point 1-3 are in below code: 
import java.lang.reflect.Field;
import ma.glasnost.orika.DefaultFieldMapper;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.metadata.ClassMapBuilder;
import ma.glasnost.orika.metadata.ClassMapBuilder.Factory;
import ma.glasnost.orika.metadata.Type;
import ma.glasnost.orika.property.PropertyResolverStrategy;

public class PlainElementToStdElementMapper extends Factory {

    @Override
    protected <A, B> ClassMapBuilder<A, B> newClassMapBuilder(
            Type<A> aType, Type<B> bType,
            MapperFactory mapperFactory,
            PropertyResolverStrategy propertyResolver,
            DefaultFieldMapper[] defaults) {
        final ClassMapBuilder<A, B> newBuilder = super.newClassMapBuilder(
                aType, bType, mapperFactory, propertyResolver, defaults);

        Field[] sourceFields = aType.getRawType().getDeclaredFields();
        Field[] destFields = bType.getRawType().getDeclaredFields();

        for (int elementA = 0; elementA < sourceFields.length; elementA++) {
            for (int elementB = 0; elementB < destFields.length; elementB++) {
                if (sourceFields[elementA].getName().equalsIgnoreCase( "Std"+destFields[elementB].getName())) {
                    newBuilder.field(sourceFields[elementA].getName(), destFields[elementB].getName());
                }
            }
        }
        return newBuilder;
    }
}


4. Create factory:

        final MapperFactory factory = new DefaultMapperFactory.Builder().
                    classMapBuilderFactory(new PlainElementToStdElementMapper()).build();

         factory.classMap(ClassA.class, ClassB.class).byDefault().register();
                MapperFacade mapperFacade = factory.getMapperFacade();