MapStruct 不复制子类属性
MapStruct does not copy subclass properties
我有以下结构。我的子类的属性没有被复制到我的 DTO。
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
class BaseClass
{
private Integer baseProperty1;
private Integer baseProperty2;
//getters & setters
}
class SubClass extends BaseClass
{
private Integer subProperty1;
private Integer subProperty2;
//getters & setters
}
class BaseSubDTO
{
private Integer baseProperty1;
private Integer baseProperty2;
private Integer subProperty1;
private Integer subProperty2;
//getters & setters
}
class BaseClassService
{
public BaseClass find()
{
return baseClassRepository.findById(101);
}
}
class BaseClassController
{
public BaseSubDTO find()
{
return mapper.toDTO(baseClassService.find());
}
}
@Mapper(componentModel = "spring")
public interface DTOMapper
{
BaseSubDTO toDTO(final BaseClass entity);
}
行:
return mapper.toDTO(baseClassService.find());
在控制器中没有将子类属性 subProperty1
、subProperty2
映射到我的 BaseSubDTO
。
如何将子类属性映射到 DTO 中?
mapstruct
似乎还不支持 Downcast 映射。参见 Support for Type-Refinement mapping (or Downcast Mapping)
为了保持通用性,您可以实现一个自定义映射器来检查传入对象的类型:
@Mapper
public interface ToDTOMapper {
ToDTOMapper MAPPER = Mappers.getMapper(ToDTOMapper.class);
BaseSubDTO toDTOFromBaseClass(BaseClass baseClass);
BaseSubDTO toDTOFromSubClass(SubClass baseClass);
default BaseSubDTO map(BaseClass baseClass) {
if(baseClass instanceof SubClass) {
return toDTOFromSubClass((SubClass)baseClass);
}
return toDTOFromBaseClass(baseClass);
}
}
用法:
SubClass subClass = ...
BaseClass baseClass = ...
ToDTOMapper mapper = ToDTOMapper.MAPPER;
BaseSubDTO dto = mapper.map(subClass);
dto = mapper.map(baseClass);
希望对您有所帮助。
这里的问题是映射器方法的实际类型用于确定映射;不考虑子类型。即,只有确切输入类型 (BaseClass
) 上的属性映射到 BaseSubDTO
,而不是任何可能在子类型上的字段(例如 SubClass
)。
当您意识到映射是在编译时根据 class 的类型完成的,而不是在运行时基于反射完成时,这就更有意义了。特别要注意的是,在编译时无法知道对于给定的超级 class 存在或将存在哪些可能的子类型,因此 MapStruct 不可能在编译时提供此功能。
话虽这么说,即将推出的 MapStruct 1.5.0 提供了一个 @SubclassMapping
注释,允许指定映射方法处理的已知子 classes。如果传入一个已知的子类型,将委托一个更具体的映射方法。
这可以应用于您的特定示例,如下所示:
@Mapper(componentModel = "spring")
public interface DTOMapper {
@SubclassMapping(source = SubClass.class, target = BaseSubDTO.class)
@Mapping(target = "subProperty1", ignore = true)
@Mapping(target = "subProperty2", ignore = true)
BaseSubDTO toDTO(final BaseClass entity);
BaseSubDTO toSubclassDTO(final SubClass entity);
}
我有以下结构。我的子类的属性没有被复制到我的 DTO。
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
class BaseClass
{
private Integer baseProperty1;
private Integer baseProperty2;
//getters & setters
}
class SubClass extends BaseClass
{
private Integer subProperty1;
private Integer subProperty2;
//getters & setters
}
class BaseSubDTO
{
private Integer baseProperty1;
private Integer baseProperty2;
private Integer subProperty1;
private Integer subProperty2;
//getters & setters
}
class BaseClassService
{
public BaseClass find()
{
return baseClassRepository.findById(101);
}
}
class BaseClassController
{
public BaseSubDTO find()
{
return mapper.toDTO(baseClassService.find());
}
}
@Mapper(componentModel = "spring")
public interface DTOMapper
{
BaseSubDTO toDTO(final BaseClass entity);
}
行:
return mapper.toDTO(baseClassService.find());
在控制器中没有将子类属性 subProperty1
、subProperty2
映射到我的 BaseSubDTO
。
如何将子类属性映射到 DTO 中?
mapstruct
似乎还不支持 Downcast 映射。参见 Support for Type-Refinement mapping (or Downcast Mapping)
为了保持通用性,您可以实现一个自定义映射器来检查传入对象的类型:
@Mapper
public interface ToDTOMapper {
ToDTOMapper MAPPER = Mappers.getMapper(ToDTOMapper.class);
BaseSubDTO toDTOFromBaseClass(BaseClass baseClass);
BaseSubDTO toDTOFromSubClass(SubClass baseClass);
default BaseSubDTO map(BaseClass baseClass) {
if(baseClass instanceof SubClass) {
return toDTOFromSubClass((SubClass)baseClass);
}
return toDTOFromBaseClass(baseClass);
}
}
用法:
SubClass subClass = ...
BaseClass baseClass = ...
ToDTOMapper mapper = ToDTOMapper.MAPPER;
BaseSubDTO dto = mapper.map(subClass);
dto = mapper.map(baseClass);
希望对您有所帮助。
这里的问题是映射器方法的实际类型用于确定映射;不考虑子类型。即,只有确切输入类型 (BaseClass
) 上的属性映射到 BaseSubDTO
,而不是任何可能在子类型上的字段(例如 SubClass
)。
当您意识到映射是在编译时根据 class 的类型完成的,而不是在运行时基于反射完成时,这就更有意义了。特别要注意的是,在编译时无法知道对于给定的超级 class 存在或将存在哪些可能的子类型,因此 MapStruct 不可能在编译时提供此功能。
话虽这么说,即将推出的 MapStruct 1.5.0 提供了一个 @SubclassMapping
注释,允许指定映射方法处理的已知子 classes。如果传入一个已知的子类型,将委托一个更具体的映射方法。
这可以应用于您的特定示例,如下所示:
@Mapper(componentModel = "spring")
public interface DTOMapper {
@SubclassMapping(source = SubClass.class, target = BaseSubDTO.class)
@Mapping(target = "subProperty1", ignore = true)
@Mapping(target = "subProperty2", ignore = true)
BaseSubDTO toDTO(final BaseClass entity);
BaseSubDTO toSubclassDTO(final SubClass entity);
}