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

ana*_*ius 7 java mapstruct

使用MapStruct。举个例子:

class Dto {
    DtoA a;
    DtoB b;
}

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

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


class Entity {
    AB ab;
}
Run Code Online (Sandbox Code Playgroud)

如何映射DtoA,并DtoB以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);
Run Code Online (Sandbox Code Playgroud)

已经生成了toABEntity足够的代码*,但未调用该方法。

*很糟糕,因为它首先设置a,然后设置b会创建的新实例ab,因此a会丢失。

jan*_*nis 3

据我了解,您想要映射EntityDto组合两个字段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);
}
Run Code Online (Sandbox Code Playgroud)

生成的映射器会覆盖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);
}
Run Code Online (Sandbox Code Playgroud)

我假设该类AB是:

class AB {
    public Long aId;
    public Long bId;
}
Run Code Online (Sandbox Code Playgroud)

生成的映射器代码:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)