Java: ModelMapper 不编译嵌套集合列表中的数据

Java: ModelMapper does not compile data in nested collection lists

我的结构类似于下面这个:

public class FirstObject {
    private List<SecondObject> myListOne;

    ...only getter method...
    ...no setter method for the list due to it is generated from wsdl 
}

public class SecondObject {
    private List<ThirdObject> myListTwo;

    ...only getter method...
    ...no setter method for the list due to it is generated from wsdl
}

public class ThirdObject {
    private String firstName;
    private String lastName;

    ...setters and getters...
}

主要问题是 setter 列表方法。如果您尝试使用 PropertyMap 或什至使用 Provider,您必须使用 setter 方法,我无法手动创建它们,因为每次我 运行 mvn [= 时,所有对象都会从 wsdl 重新生成29=]命令。

更新:

你可以在下面link找到我的源代码: https://github.com/ervinfetic/modelmapper-issue-one

有什么解决办法可以用Converter实现吗??

如果你不能有setter,你可以配置ModelMapper按字段访问。只需像您的列表属性一样将 FieldMatching 和 FieldAccessLevel 设为私有

modelMapper.getConfiguration()
  .setFieldMatchingEnabled(true)
  .setFieldAccessLevel(AccessLevel.PRIVATE);

示例:

Class FirstObject:

public class FirstObject {

    private String name;

    private List<FirstObjectList> objectList = new ArrayList<FirstObjectList>();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<FirstObjectList> getObjectList() {
        return objectList;
    }
}

Class FirstObjectList:

public class FirstObjectList {

    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

}

所以我们希望将 FirstObject 映射到我们的 SecondObject class,它具有完全相同的结构(属性):

Class SecondObject:

public class SecondObject {

    private String name;

    private List<SecondObjectList> objectList;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<SecondObjectList> getObjectList() {
        return objectList;
    }

}

Class SecondObjectList:

public class SecondObjectList {

    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}

然后我们需要创建我们的ModelMapper实例并将其配置为字段匹配和私有访问级别。

public void test(){
    ModelMapper mapper = new ModelMapper();
    mapper.getConfiguration().setFieldMatchingEnabled(true);
    mapper.getConfiguration().setFieldAccessLevel(Configuration.AccessLevel.PRIVATE);


    FirstObject firstObject = new FirstObject();
    firstObject.setName("Hola");

    FirstObjectList firstObjectList = new FirstObjectList();
    firstObjectList.setId("1");

    firstObject.getObjectList().add(firstObjectList);

    SecondObject second = mapper.map(firstObject, SecondObject.class);

    assertEquals(firstObject.getName(), second.getName());

    assertEquals(firstObject.getObjectList().size(), second.getObjectList().size());    
    assertEquals(firstObject.getObjectList().get(0).getId(), second.getObjectList().get(0).getId());
}

一切都已完美映射。所以它有效。

  • 输出:

SecondObject{name='Hola', objectList=[SecondObjectList{id='1'}]}

但如果没有启用 FieldMatching 或将字段访问级别设置为私有,您的列表将不会被映射:

  • 输出:

SecondObject{name='Hola', objectList=null}

更新

如果您有嵌套列表,您可以将命名约定设置为修改器以避免多重匹配错误,只需像下一步一样配置它:

 modelMapper.getConfiguration()
.setSourceNamingConvention(NamingConventions.JAVABEANS_MUTATOR);

否则,如果你不想通过字段访问来做,你可以创建一个Converter来处理这种匹配:

public class ListConverter implements Converter<List<SecondObject>, List<ThirdObject>> {

    @Override
    public List<ThirdObject> convert(MappingContext<List<SecondObject>, List<PromoConditionEntity>> context) {
       //A java 8 mapping example
       return context.getSource()
          .stream()
          .map(this::convertToThirdObject)
        .collect(Collectors.toList());
    }

    private ThirdObject convertToThirdObject(SecondObject s) {
       //your impl map SecondObject to ThirdObject
       ...
     }
}

最后,不要忘记将转换器添加到您的模型映射器实例中:

modelMapper.addConverter(new ListConverter());