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

时间:2017-03-30 10:29:10

标签: java maven spring-mvc mapping modelmapper

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

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或甚至使用Providers,您必须使用setter方法,我无法手动创建它们,因为每次运行 mvn eclipse:eclipse 命令时,所有对象都将从wsdl重新生成。

更新

您可以在以下链接中找到我的源代码: https://github.com/ervinfetic/modelmapper-issue-one

有没有解决方法如何使用Converter?

1 个答案:

答案 0 :(得分:1)

如果您无法设置设置器,则可以配置ModelMapper按字段访问。只需将FieldMatching和FieldAccessLevel设置为像列表属性一样私有

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

示例:

班级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;
    }
}

班级FirstObjectList

public class FirstObjectList {

    private String id;

    public String getId() {
        return id;
    }

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

}

因此,我们希望将FirstObject映射到具有完全相同结构(属性)的SecondObject类:

班级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;
    }

}

班级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}

更新

如果你有嵌套列表,你可以将命名约定设置为mutators以避免多个匹配错误,只需像下一个那样进行配置:

 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 isntance:

modelMapper.addConverter(new ListConverter());