Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Map to Generic Type?

Tags:

mapstruct

PageInfoDto

public class PageInfoDto<T> implements Serializable {

    private int currentPageNum;

    private int totalPageNum;

    private int perPageNum;

    private int totalItemNum;

    private List<T> list;

}

Page

public class Page<T> implements Serializable {

    private int current;

    private int total;

    private int size;

    private int items;

    private List<T> list;

}

say, i have a school list and a student list.

i want to map Page to PageInfoDto and map Page to PageInfoDto。

this is how my mapper looks like;


@Mapper( config = CentralConfig.class, uses = {StudentMapper.class, SchoolMapper.class}, componentModel = "spring")
public interface PageInfoMapper {

    @Mappings({
            @Mapping(target = "list", source = "pageInfo.records"),
            @Mapping(target = "currentPageNum", source = "pageInfo.current"),
            @Mapping(target = "totalPageNum", source = "pageInfo.pages"),
            @Mapping(target = "perPageNum", source = "pageInfo.size"),
            @Mapping(target = "totalItemNum", source = "pageInfo.total"),
    })
    PageInfoDto<SchoolDto> toPageInfoDto1(Page<School> pageInfo);

    @Mappings({
            @Mapping(target = "list", source = "pageInfo.records"),
            @Mapping(target = "currentPageNum", source = "pageInfo.current"),
            @Mapping(target = "totalPageNum", source = "pageInfo.pages"),
            @Mapping(target = "perPageNum", source = "pageInfo.size"),
            @Mapping(target = "totalItemNum", source = "pageInfo.total"),
    })
    PageInfoDto<StudentDto> toPageInfoDto2(Page<Student> pageInfo);

}

this obviously not a clever way to do . is there a better way to do this?

like image 475
5468sun Avatar asked Mar 03 '23 15:03

5468sun


1 Answers

Mapstruct is a code generator. So it needs to know which types to construct in order to generate a method implementation. Having said that, you could do this smarter by using a base mapping method on which you define all the @Mapping annotations and ignore the generic type mapping. You still have the methods above but you just specify @InheritConfiguration

Alternatively you could consider playing around with an objectfactory using @TargetType to construct the proper generic type. I'm not sure whether that works with a generic mapping method signature. I'm not in the position to check it, but let me know if that works

E.g.

    public interface BasePageMapper<S, DTO> {

        @Mapping(target = "list", source = "records"),
        @Mapping(target = "currentPageNum", source = "current"),
        @Mapping(target = "totalPageNum", source = "pages"),
        @Mapping(target = "perPageNum", source = "size"),
        @Mapping(target = "totalItemNum", source = "total"),
        PageInfoDto<DTO> toPageInfoDto(Page<S> pageInfo);

        DTO toDto(S source);
    }

@Mapper( config = CentralConfig.class, uses = StudentMapper.class, componentModel = "spring")
    public interface StudentMapper extends BasePageMapper<Student, StudentDto> {

    }

@Mapper( config = CentralConfig.class, uses = SchoolMapper.class, componentModel = "spring")
    public interface SchoolMapper extends BasePageMapper<School, SchoolDto> {

    }
like image 120
Sjaak Avatar answered Mar 12 '23 01:03

Sjaak