不同fieldNames的orika customMap的反射

时间:2017-03-23 17:08:01

标签: java hibernate-mapping webservice-client orika

假设我们有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;
}

如何使用通用代码(或反射/自定义)映射这些DTO,即不使用:

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

2 个答案:

答案 0 :(得分:0)

如果您询问如何将常用属性从一个表示(ClassA)映射到另一个表示(ClassB),则可以使用part 2中显示的byDefault()

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

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

答案 1 :(得分:0)

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();