Сопоставление двух объектов, содержащих список, с использованием Orika

Я пытаюсь использовать Orika для сопоставления двух объектов, содержащих List<...>, где тип списка является другим объектом, однако, несмотря на попытки различных перестановок конфигурации сопоставления в mapperFactory.classMap(...), Orika выдает исключение при запуске моей программы.

Глядя на http://orika-mapper.github.io/orika-docs/mappings-via-classmapbuilder.html кажется, что этот синтаксис для сопоставления List должен быть parentProperty{childProperty}.

Для целей этого вопроса я упростил объекты, которые я пытаюсь отобразить. Исходный объект — ToDoTaskListEntity, а конечный объект — ToDoTaskListDTO. Исходный объект ToDoItemEntity содержит список, который определяется как List<ToDoItemEntity>, а целевой объект содержит соответствующий список, который определяется как List<ToDoItemDTO>.

Мой вопрос: как определить конфигурацию сопоставления в Orika между ToDoTaskListEntity и ToDoTaskListDTO, чтобы дочерний объект List<ToDoItemEntity> также сопоставлялся с List<ToDoItemDTO> в соответствующих родительских объектах?


Код для моей конфигурации отображения выглядит следующим образом:

MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();

mapperFactory.classMap(ToDoItemEntity.class, ToDoItemDTO.class)
    .field("id", "id")
    .field("description", "description")
    .field("status", "status")
    .byDefault()
    .register();

mapperFactory.classMap(ToDoTaskListEntity.class, ToDoTaskListDTO.class)
    .field("listName", "listName")
    .field("toDoItems{id}", "toDoItems{id}")
    .field("toDoItems{description}", "toDoItems{description}")
    .field("toDoItems{status}", "toDoItems{status}")
    .byDefault()
    .register();

Код для вызова сопоставления выглядит следующим образом:

MapperFacade mapper = mapperFactory.getMapperFacade();
ToDoTaskListDTO toDoTaskListDTO = mapper.map(toDoTaskListEntity, ToDoTaskListDTO.class);

Код для моих исходных объектов выглядит следующим образом:

public class ToDoTaskListEntity {

    private String ListName;
    private List<ToDoItemEntity> toDoItems;

    // Getters and setters
}

public class ToDoItemEntity {

    private int id;
    private String description;
    private Status status;

    // Getters and setters
}

Код для моих объектов назначения выглядит следующим образом:

public class ToDoTaskListDTO {

    private String listName;
    private List<ToDoItemDTO> toDoItems;

    public ToDoTaskListDTO(String listName, List<ToDoItemDTO> toDoItems) {
        this.listName = listName;
        this.toDoItems = toDoItems;
    }

    //Getters but no setters

}

public class ToDoItemDTO {

    private int id;
    private String description;
    private Status status;

    public ToDoItemDTO(int id, String description, Status status) {
        this.id = id;
        this.description = description;
        this.status = status;
    }

    // Getters but no setters
}

Исключение, созданное Orika, выглядит следующим образом:

Exception in thread "main" ma.glasnost.orika.MappingException: exception while creating object factory for test.orikademo.ToDoTaskListDTO
-----begin dump of current state-----------------------------
Registered object factories: 1 (approximate size: 25.4 kB)
  [ToDoTaskListDTO] : {}
-------------------------------------------------------------
Registered mappers: 2 (approximate size: 961.5 kB)
  [0] : GeneratedMapper<ToDoItemEntity, ToDoItemDTO> {usedConverters: [], usedMappers: [], usedMapperFacades: [], usedTypes: [] }
  [1] : GeneratedMapper<ToDoTaskListEntity, ToDoTaskListDTO> {usedConverters: [], usedMappers: [], usedMapperFacades: [DefaultBoundMapperFacade<ToDoItemEntity, ToDoItemDTO>], usedTypes: [List<ToDoItemEntity>, List<ToDoItemDTO>] }
-------------------------------------------------------------
Registered concrete types: 5 (approximate size: 122.4 kB)
  [interface java.util.List] : ArrayList<Object>
  [interface java.util.Set] : LinkedHashSet<Object>
  [interface java.util.Collection] : ArrayList<Object>
  [interface java.util.Map$Entry] : MapEntry<Object, Object>
  [interface java.util.Map] : LinkedHashMap<Object, Object>
-------------------------------------------------------------
Resolved strategies: 0 (approximate size: 0.8 kB)
-------------------------------------------------------------
Unenhance strategy: ma.glasnost.orika.unenhance.BaseUnenhancer@292a74d5
-----end dump of current state-------------------------------
    at ma.glasnost.orika.impl.generator.ObjectFactoryGenerator.build(ObjectFactoryGenerator.java:110)
    at ma.glasnost.orika.impl.DefaultMapperFactory.lookupObjectFactory(DefaultMapperFactory.java:1005)
    at ma.glasnost.orika.impl.DefaultMapperFactory.lookupObjectFactory(DefaultMapperFactory.java:925)
    at ma.glasnost.orika.impl.MapperFacadeImpl.resolveMappingStrategy(MapperFacadeImpl.java:218)
    at ma.glasnost.orika.impl.MapperFacadeImpl.map(MapperFacadeImpl.java:734)
    at ma.glasnost.orika.impl.MapperFacadeImpl.map(MapperFacadeImpl.java:714)
    at test.orikademo.App.main(App.java:54)
Caused by: java.lang.NullPointerException
    at ma.glasnost.orika.impl.generator.ObjectFactoryGenerator.addSourceClassConstructor(ObjectFactoryGenerator.java:173)
    at ma.glasnost.orika.impl.generator.ObjectFactoryGenerator.addCreateMethod(ObjectFactoryGenerator.java:124)
    at ma.glasnost.orika.impl.generator.ObjectFactoryGenerator.build(ObjectFactoryGenerator.java:95)
    ... 6 more

person Paul H    schedule 07.04.2015    source источник


Ответы (1)


Я разместил тот же вопрос в группе обсуждения Orika в группах Google. и получил следующий ответ от Сиди Мохамеда, который решил мою проблему.

Вам не нужны какие-либо специальные сопоставления для этого примера, единственная проблема, которую я здесь вижу, это конструктор не по умолчанию на стороне DTO.

MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
// item class map
mapperFactory.classMap(ToDoItemEntity.class, ToDoItemDTO.class)
    .constrcutorB("id", "description", "status")
    .byDefault()
    .register();

mapperFactory.classMap(ToDoTaskListEntity.class, ToDoTaskListDTO.class)
    .constructorB("listName", "toDoItems")
    .byDefault()
    .register();

Чтобы ответить на ваш вопрос, выражение, подобное toDoItems{id}, используется только для проецирования (или выравнивания) ваших объектов, в этом примере вам нужно повторно использовать ваши предыдущие определения сопоставления (например, повторно использовать карту класса элементов при сопоставлении toDoItems во втором class map), для чего и используется Orika: чтобы сократить шаблонный код.

person Paul H    schedule 10.04.2015