mapstruct map迭代到非迭代

时间:2019-03-25 15:28:41

标签: spring iterable mapstruct

我想将对象列表映射到包含列表的对象:

public class Group {
    private List<Person> people;
}

public class Person {
    private String name;
}

我试图创建一个像这样的映射器:

Group toGroup(List<Person> people);

我收到此错误:

error: Can't generate mapping method from iterable type to non-iterable type.

这种映射最优雅的解决方案是什么?

1 个答案:

答案 0 :(得分:0)

问题的名称有点不正确。

常规答案-禁止这种映射。

将对象列表映射到将包装该列表的对象可以通过以下方式完成:

/// your class with business code
List<Person> people = ....
new Group(people);

/// group class
public class Group {
    private List<Person> people = new ArrayList<>();
    public Group(List<Person> people) {
       this.people = people
    }
}

Group只是带有列表作为参数的构造函数时。您不需要为此使用Mapstruct。 在mapstruct来源中,有以下检查Mapstruct github sources for MethodRetrievalProcessor.java

        Type parameterType = sourceParameters.get( 0 ).getType();

        if ( parameterType.isIterableOrStreamType() && !resultType.isIterableOrStreamType() ) {
            messager.printMessage( method, Message.RETRIEVAL_ITERABLE_TO_NON_ITERABLE );
            return false;
        }

因此,基本上,甚至Mapstruct团队也希望您仅在需要时使用映射。并且不希望将List<Object>转换为另一个Object,因为这没有意义。 如果您要为Group对象添加一些其他信息(不可迭代:),这将是有道理的,例如:

//group class
public class Group {
    private Long someCounter;
    private List<Person> people;
}

//mapper
@Mapping(target= "people", source ="people")
@Mapping(target= "someCounter", source ="counterValue")
Group toGroup(Long counterValue, List<Person> people);

但是最好使用DTO,视图,实体以及任何其他可以隐藏所有嵌套内容的对象。在这种情况下,Mapstruct将是您最大的朋友。