【发布时间】:2020-03-01 09:48:03
【问题描述】:
我正在开发一个 Springboot 应用程序,该应用程序公开了一些不返回原始实体但返回其 DTO 的端点。为了映射我正在使用“org.modelmapper”版本的所有实体:0.7.4 和项目 lombok 以避免实现 getter、setter 和其他一些实用程序。
在我不得不在实体上映射子类列表之前,一切都运行良好。源实体是这样的(我删除了一些属性和休眠注释,因为它们在示例中不是必需的):
package com.pfi.repository.entity.sport;
import com.pfi.repository.entity.address.Address;
import lombok.*;
import java.util.List;
@Getter
@Setter
@EqualsAndHashCode
@AllArgsConstructor
@NoArgsConstructor
public class SportPlace {
private Long id;
private List<AbstractSportField> sportFields;
}
目标 DTO 是:
package dto.sport;
import lombok.*;
import java.util.List;
@Getter
@NoArgsConstructor
@Setter
public class SportPlaceDTO {
private Long id;
private List<AbstractSportFieldDTO> sportFields;
}
AbstractSportFieldDTO 和 AbstractSportField 都是抽象类,有两个可能的子类:
package dto.sport;
import dto.reserve.AbstractReserveDTO;
import java.util.List;
public abstract class AbstractSportFieldDTO {
protected Long id;
protected List<AbstractReserveDTO> reserves;
public AbstractSportFieldDTO() {
}
public AbstractSportFieldDTO(Long id, List<AbstractReserveDTO> reserves) {
this.id = id;
this.reserves = reserves;
}
public Long getId() {
return id;
}
public AbstractSportFieldDTO setId(Long id) {
this.id = id;
return this;
}
public List<AbstractReserveDTO> getReserves() {
return reserves;
}
public AbstractSportFieldDTO setReserves(List<AbstractReserveDTO> reserves) {
this.reserves = reserves;
return this;
}
}
第一个 DTO 子类是:
package dto.sport;
import dto.reserve.AbstractReserveDTO;
import java.util.List;
public class ComboSportFieldDTO extends AbstractSportFieldDTO {
private List<SportFieldDTO> sportFields;
public ComboSportFieldDTO(List<SportFieldDTO> sportFields) {
this.sportFields = sportFields;
}
public ComboSportFieldDTO(Long id, List<AbstractReserveDTO> reserves, List<SportFieldDTO> sportFields) {
super(id, reserves);
this.sportFields = sportFields;
}
public ComboSportFieldDTO() {
super();
}
public List<SportFieldDTO> getSportFields() {
return sportFields;
}
public void setSportFields(List<SportFieldDTO> sportFields) {
this.sportFields = sportFields;
}
}
第二个 DTO 子类是:
package dto.sport;
import dto.reserve.AbstractReserveDTO;
import java.util.List;
public class SportFieldDTO extends AbstractSportFieldDTO {
private Boolean joineable;
public SportFieldDTO(Long id, List<AbstractReserveDTO> reserves, Boolean joineable) {
super(id, reserves);
this.joineable = joineable;
}
public SportFieldDTO() {
super();
}
public Boolean getJoineable() {
return joineable;
}
public void setJoineable(Boolean joineable) {
this.joineable = joineable;
}
}
那么实体是:
package com.pfi.repository.entity.sport;
import com.pfi.repository.entity.reserve.AbstractReserve;
import java.util.List;
public abstract class AbstractSportField {
protected Long id;
protected List<AbstractReserve> reserves;
public AbstractSportField(Long id, List<AbstractReserve> reserves) {
this.id = id;
this.reserves = reserves;
}
public AbstractSportField() {
}
public Long getId() {
return id;
}
public AbstractSportField setId(Long id) {
this.id = id;
return this;
}
public List<AbstractReserve> getReserves() {
return reserves;
}
public AbstractSportField setReserves(List<AbstractReserve> reserves) {
this.reserves = reserves;
return this;
}
}
第一个子类是:
package com.pfi.repository.entity.sport;
import com.pfi.repository.entity.reserve.AbstractReserve;
import java.util.List;
public class ComboSportField extends AbstractSportField {
private List<SportField> sportFields;
public ComboSportField(Long id, List<AbstractReserve> reserves, List<SportField> sportFields) {
super(id, reserves);
this.sportFields = sportFields;
}
public ComboSportField(){
super();
}
public List<SportField> getSportFields() {
return sportFields;
}
public ComboSportField setSportFields(List<SportField> sportFields) {
this.sportFields = sportFields;
return this;
}
}
最后一个子类是:
package com.pfi.repository.entity.sport;
import com.pfi.repository.entity.reserve.AbstractReserve;
import javax.persistence.Entity;
import java.util.List;
public class SportField extends AbstractSportField {
private Boolean joineable;
public SportField(Long id, List<AbstractReserve> reserves, Boolean joineable) {
super(id, reserves);
this.joineable = joineable;
}
public SportField(){
super();
}
public Boolean getJoineable() {
return joineable;
}
public SportField setJoineable(Boolean joineable) {
this.joineable = joineable;
return this;
}
}
当我尝试像这样将 SportPlace 的实例映射到 SportPlaceDTO 时:
modelMapper.map(sportPlace, SportPlaceDTO.class)
de sportPlace 包含给定的 6 个作为子类实例的运动场。模型映射器抛出(在列表的 6 个元素上):
无法实例化目标 dto.sport.AbstractSportFieldDTO 的实例。确保 dto.sport.AbstractSportFieldDTO 有一个非私有的无参数构造函数。
阅读有关如何在 modelmapper 上映射子类的信息,我发现设置 TypeMap,可以像这样在类上设置特定映射:
modelMapper.createTypeMap(ComboSportField.class, ComboSportFieldDTO.class);
出于这个原因,我创建了一个构建器来像这样配置模型映射器
package com.pfi.repository.builder;
import com.pfi.repository.entity.*;;
import dto.reserve.*;
import dto.sport.*;
import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;
import org.springframework.stereotype.Service;
@Service
public class MapperBuilder {
public ModelMapper buildModelMapper() {
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
mapEntitiesToDTO(modelMapper);
mapDTOToEntities(modelMapper);
return modelMapper;
}
private void mapEntitiesToDTO(final ModelMapper modelMapper){
modelMapper.createTypeMap(ComboSportField.class, ComboSportFieldDTO.class);
modelMapper.createTypeMap(SportField.class, SportFieldDTO.class);
modelMapper.createTypeMap(Reserve.class, ReserveDTO.class);
modelMapper.createTypeMap(AppReserve.class, AppReserveDTO.class);
}
private void mapDTOToEntities(final ModelMapper modelMapper){
modelMapper.createTypeMap(ComboSportFieldDTO.class, ComboSportField.class);
modelMapper.createTypeMap(SportFieldDTO.class, SportField.class);
modelMapper.createTypeMap(ReserveDTO.class, Reserve.class);
modelMapper.createTypeMap(AppReserveDTO.class, AppReserve.class);
}
}
当我像这样创建控制器时,我会使用构建器:
@Autowired
protected MapperBuilder mapperBuilder;
BaseController(){
this.getLogger();
}
@PostConstruct
public void buildMapper(){
modelMapper = mapperBuilder.buildModelMapper();
}
我不知道我还能做些什么来映射子类。
有人知道如何解决这个问题吗?
谢谢!
【问题讨论】:
标签: java spring-boot inheritance dto modelmapper