从多个源 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;
}
如何将 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);
尽管已生成代码*,但未调用方法 toABEntity
。
*很糟糕,因为它先设置 a
,然后设置 b
会创建一个新的 ab
实例,所以 a
丢失了。
据我了解,您想要将 Entity
映射到 Dto
,并将两个字段 Dto.a
和 Dto.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;
}
}
使用 MapStruct。举个例子:
class Dto {
DtoA a;
DtoB b;
}
class DtoA {
Long id;
//...
}
class DtoB {
Long id;
//...
}
class Entity {
AB ab;
}
如何将 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);
尽管已生成代码*,但未调用方法 toABEntity
。
*很糟糕,因为它先设置 a
,然后设置 b
会创建一个新的 ab
实例,所以 a
丢失了。
据我了解,您想要将 Entity
映射到 Dto
,并将两个字段 Dto.a
和 Dto.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;
}
}