Каскадные PropertyMaps с ModelMapper - PullRequest
3 голосов
/ 12 января 2012

Рассмотрим 6 классов POJO: 3 DAO и 3 DTO.

DAO: "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».
«Один» содержит список «двух». «Два» содержит список «трех».

«A» отображается на «One» через «A2One». «B» отображается на «Two» через «B2Two». «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», выполняется с помощью пользовательского преобразователя (и он работает), но я повторяю ту же операцию, которую должен выполнить B2Two (сопоставить Bs и Twos) .

Существует ли какой-либо способ каскадного отображения Карт свойств (A2One -> B2Two -> C2Three), когда список должен отображаться без необходимости писать конвертер, который просто воспроизводит действия карт свойств?

Альтернатива 1 : создание пользовательской карты типов с обобщениями List, List, которая пересылает правильную карту свойств / типов.

Альтернатива 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 в основном мертв и фактически не поддерживает списки или каскадирование отображений, так что вам придется писать карту и конвертер для каждого объекта, который также может быть списком.
Кроме того, я обнаружил, что у Orika есть удобные для рефакторинга отображения за счет расширения MapperBase Более того, Orika может прозрачно работать с отображениями отдельных bean-компонентов и списков bean-компонентов (используя одно правило отображения для обеих ситуаций).

Обновление 2 : В Orika возможно делать двунаправленное глубокое вложенное отображение коллекций, используя CustomMapper. Это дает возможность создания реализаций двунаправленного отображения и позволяет их каскадно подключать к другим настраиваемым картографам. A2One будет содержать экземпляр B2Two и использовать его прозрачно при отображении «B», содержащихся в «A».

Ответы [ 2 ]

1 голос
/ 03 февраля 2016

Я думал, что просто укажу, что теперь это возможно с моделью картографа ...

Поддерживает списки (по крайней мере, в версии 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);
    }
}
1 голос
/ 21 января 2015

Используя Orika, я смог получить все необходимые требования простым и дружественным способом.

...