java 使用 Orika 在包含列表的两个对象之间进行映射

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29489148/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 15:22:30  来源:igfitidea点击:

Mapping between two objects that contain a List using Orika

javalistmappingorika

提问by Paul H

I am trying to use Orika to map between two objects that contain a List<...>where the List type is another object, however despite trying various permutations of the mapping configuration in mapperFactory.classMap(...)Orika throws an exception when I run my program.

我正在尝试使用 Orika 在包含List<...>列表类型是另一个对象的两个对象之间进行映射,但是尽管在mapperFactory.classMap(...)Orika 中尝试了映射配置的各种排列,但在我运行我的程序时仍会引发异常。

Looking at http://orika-mapper.github.io/orika-docs/mappings-via-classmapbuilder.htmlit seems to suggest that that syntax for mapping a Listshould be parentProperty{childProperty}.

查看http://orika-mapper.github.io/orika-docs/mappings-via-classmapbuilder.html似乎表明映射 a 的语法List应该是parentProperty{childProperty}.

For the purposes of this question I've simplified the objects that I'm trying to map. The source object is ToDoTaskListEntityand the destination object is ToDoTaskListDTO. The source object ToDoItemEntitycontains a List which is defined as List<ToDoItemEntity>and the destination object contains a corresponding List which is defined as List<ToDoItemDTO>

出于这个问题的目的,我已经简化了我试图映射的对象。源对象是ToDoTaskListEntity,目标对象是ToDoTaskListDTO。源对象ToDoItemEntity包含一个定义为的列表,List<ToDoItemEntity>目标对象包含一个对应的列表,定义为List<ToDoItemDTO>

My question ishow should I define the mapping configuration in Orika between ToDoTaskListEntityand ToDoTaskListDTOso that the child object List<ToDoItemEntity>is also mapped to List<ToDoItemDTO>within their respective parent objects?

我的问题是我应该如何在 Orika 之间定义映射配置ToDoTaskListEntityToDoTaskListDTO以便子对象List<ToDoItemEntity>也映射到List<ToDoItemDTO>它们各自的父对象内?



The code for my mapping configuration is as follows:

我的映射配置代码如下:

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

The code for invoking the mapping is as follows:

调用映射的代码如下:

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

The code for my source objects is as follow:

我的源对象的代码如下:

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
}

The code for my destination objects is as follow:

我的目标对象的代码如下:

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
}

The exception that thrown by Orika is as follow:

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

采纳答案by Paul H

I posted the same question in the Orika discussion groupon Google Groups and got the following answer from Sidi Mohamed which solved my problem.

我在 Google Groups的Orika 讨论组中发布了相同的问题,并从 Sidi Mohamed 那里得到了以下答案,这解决了我的问题。

You do not need any specific mappings for this example, the only issue I can see here is the non default constructor on the DTO side

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

To answer your question the expression like toDoItems{id} is used only to project (or flatten) your objects, in this example what you want is to re use your previous mapping definitions (eg. reuse item class map when mapping toDoItems in the second class map) which why Orika is used : to reduce the boilerplate code.

您不需要此示例的任何特定映射,我在这里看到的唯一问题是 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 时重用项目类映射类映射)为什么使用 Orika:减少样板代码。