首页 文章

使用ModelMapper级联PropertyMaps

提问于
浏览
3

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

DAOs:"A","B","C"
DTO:"One","Two","Three"

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 - > B2Two - > C2Three)而无需编写仅仅重现属性映射正在执行的转换器的转换器?

Alternative 1 :使用泛型 List, List 创建自定义TypeMap,前往正确的属性/类型映射 .

Alternative 2 :在A2One中,使用以下列表

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

ListProvider扩展AbstractProvider返回新的ArrayList()

Alternative 3 :???

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

提前致谢

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

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

2 回答

  • 2

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

  • 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);
        }
    }
    

相关问题