从多个源 DTO 映射到一个目标

Map from multiple sources DTOs to one target

使用 MapStruct。举个例子:

class Dto {
    DtoA a;
    DtoB b;
}

class DtoA {
    Long id;
    //...
}

class DtoB {
    Long id;
    //...
}


class Entity {
    AB ab;
}

如何将 DtoADtoB 映射到 AB?

我试过了:

public abstract Entity toEntity(Dto dto);

@Mappings({
            @Mapping(source = "a", target = "ab.a"),
            @Mapping(source = "b", target = "ab.b")
)}
public abstract AB toABEntity(DtoA a, DtoB b);

尽管已生成代码*,但未调用方法 toABEntity

*很糟糕,因为它先设置 a,然后设置 b 会创建一个新的 ab 实例,所以 a 丢失了。

据我了解,您想要将 Entity 映射到 Dto,并将两个字段 Dto.aDto.b 合并为一个字段 Entity.ab

通常当您尝试这样做时:

@Mapper
public interface TestMapper {
    @Mappings({
        @Mapping(source = "a.id", target = "ab.aId", qualifiedByName = "toAB"),
        @Mapping(source = "b.id", target = "ab.bId", qualifiedByName = "toAB"),
    })
    Entity toEntity(Dto dto);
}

生成的映射器覆盖 ab 每个 @Mapping 的实例,在 ab 中有一个目标 属性。这显然是一个错误,在 MapStructs GitHub: https://github.com/mapstruct/mapstruct/issues/1148

上有一张票

虽然有一个解决方法:

@Mapper
public interface TestMapper {
    @Mappings({
        @Mapping(source = "dto", target = "ab", qualifiedByName = "toAB"),
    })
    Entity toEntity(Dto dto);

    @Mappings({
        @Mapping(target = "aId", source = "a.id"),
        @Mapping(target = "bId", source = "b.id"),
    })
    AB toAB(Dto dto);
}

我假设 AB class 是:

class AB {
    public Long aId;
    public Long bId;
}

生成的映射器代码:

public class TestMapperImpl implements TestMapper {

    @Override
    public Entity toEntity(Dto dto) {
        if ( dto == null ) {
            return null;
        }

        Entity entity = new Entity();

        entity.ab = toAB( dto );

        return entity;
    }

    @Override
    public AB toAB(Dto dto) {
        if ( dto == null ) {
            return null;
        }

        AB aB = new AB();

        Long id = dtoBId( dto );
        if ( id != null ) {
            aB.bId = id;
        }
        Long id1 = dtoAId( dto );
        if ( id1 != null ) {
            aB.aId = id1;
        }

        return aB;
    }

    private Long dtoBId(Dto dto) {
        if ( dto == null ) {
            return null;
        }
        DtoB b = dto.b;
        if ( b == null ) {
            return null;
        }
        Long id = b.id;
        if ( id == null ) {
            return null;
        }
        return id;
    }

    private Long dtoAId(Dto dto) {
        if ( dto == null ) {
            return null;
        }
        DtoA a = dto.a;
        if ( a == null ) {
            return null;
        }
        Long id = a.id;
        if ( id == null ) {
            return null;
        }
        return id;
    }
}