使用ModelMapper级联PropertyMaps

时间:2012-01-12 14:22:37

标签: java mapping orika modelmapper

考虑6个POJO类:3个DAO和3个DTO。

DAOs:“A”,“B”,“C”
DTO:“一个”,“两个”,“三个”

public class A {

    private int idOfA;
    private String name;
    private List<B> b;

    // getters, setters, etc...
}

public class B {

    private int idOfB;
    private String name;
    private List<C> c;

    // getters, setters, etc...
}

public class C {

    private int idOfC;
    private String name;

    // getters, setters, etc...
}



public class One {

    private int id;
    private String name;
    private List<Two> two;

    // getters, setters, etc...
}

public class Two {

    private int id;
    private String name;
    private List<Three> Three;

    // getters, setters, etc...
}

public class Three {

    private int id;
    private String name;

    // getters, setters, etc...
}

“A”包含“B”列表。 “B”包含“C”列表 “One”包含“Two”列表。 “Two”包含“Three”列表。

“A”通过“A2One”映射到“One”。 “B”通过“B2Two”映射到“Two”。 “C”通过“C2Three”映射到三。

public class A2One extends PropertyMap<A, One> {

    @Override
    protected void configure() {
        map().setId(source.getIdOfA());
        map().setName(source.getName());

        when(Conditions.isNotNull()).using(new BListConverter()).map(source.getBs()).setTwos(null);
    }
}

public class BListConverter extends AbstractConverter<List<B>, List<Two>> {

        @Override
        protected List<Two> convert(List<B> source) {

            List<Two> twos = new ArrayList<Two>(source.size());

            for(B b : source) {
                Two t = new Two();
                t.setId(b.getId());
                t.setName(b.getName());

                // Ignore list of Cs contained in B for now

                twos.add(t);
            }

            return twos;
        }
}

public class B2Two extends PropertyMap<B, Two> {

    @Override
    protected void configure() {
        map().setId(source.getIdOfB());
        map().setName(source.getName());

        when(Conditions.isNotNull()).using(new CListConverter()).map(source.getCs()).setThrees(null);
    }
}

B2Two和C2Three与A2One的代码非常相似。

所以这是我的问题:

目前,“A”和“One”中包含的List之间的转换是通过自定义转换器完成的(它可以正常工作),但是我正在重复B2Two应该执行的相同操作(将Bs映射到Twos)

是否有任何方法可以在映射List时级联Property Property(A2One - &gt; B2Two - &gt; C2Three)而无需编写仅仅重现属性映射正在执行的转换器?

备选方案1 :使用泛型List, List创建自定义TypeMap,转发到正确的属性/类型映射。

备选方案2 :在A2One中,使用以下内容列表

mapper.addMappings(new BList2TwoList());
when(Conditions.isNotNull()).withProvider(listProvider).map().setTwos(mapper.map(source.getBs(), List.class));

ListProvider扩展AbstractProvider返回新的ArrayList()

备选方案3 :???

有什么想法吗?更多涉及映射问题的文档在网站上非常糟糕,我不一定在寻找替代框架。如果提供替代方案,它们必须允许轻松重构(因此Dozer和Orika基本上都没有)。

提前致谢

更新: 在撰写时,ModelMapper的编写时间为basically dead,并且实际上不支持列表或级联映射,因此您将被迫为每个可以作为列表的对象编写映射和转换器。
此外,我发现Orika通过扩展MapperBase来实现重构友好映射。此外,Orika可以透明地处理单个bean和bean列表的映射(对于这两种情况使用单个映射规则)。

更新2 : 在Orika中,可以使用CustomMapper对集合进行双向深层嵌套映射。这样可以创建双向映射实现,并允许它们级联到其他自定义映射器。 A2One将保存B2Two的实例,并在映射“A”中包含的“B”时透明地使用它。

2 个答案:

答案 0 :(得分:2)

使用Orika我能够以简单友好的方式获得我所需的所有要求。

答案 1 :(得分:1)

我想我只是表明现在可以使用模型映射器......

它支持列表(至少在版本0.7.5上)。

执行此操作的属性图如下所示:

public class A2One extends PropertyMap<A, One> {

    @Override
    protected void configure() {
        map().setId(source.getIdOfA());
        map().setName(source.getName());

        map(source.getB()).setOne(null);
    }
}