我目前正在使用 ModelMapper。从我的角度来看,这非常用户友好。但是,由于性能问题,我需要迁移到 MapStruct。想象一下我有如下
Tariff
课程
@Setter @Getter @Builder @ToString
@AllArgsConstructor @NoArgsConstructor
@Entity
@Table(name = "tariff")
public class Tariff {
@Id
@Column(name = "id")
private String id;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "id_energy_mix")
private EnergyMix energyMix;
我的
TariffDTO
如下
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class TariffDTO {
@JsonProperty("id")
@SerializedName("id")
private String id;
@JsonProperty("id_energy_mix")
@SerializedName("id_energy_mix")
private EnergyMixDTO energyMix;
当我需要将 Tariff 转换为 TariffDTO 时,我使用 ModelMapper 如下
public TariffDTO mapperTariffToDTO(Tariff tariff) {
ModelMapper modelMapper = new ModelMapper();
TypeMap<Tariff, TariffDTO> typeMap = modelMapper.createTypeMap(Tariff.class, TariffDTO.class);
if (tariff.getEnergyMix() != null) {
typeMap.addMappings(mapper -> mapper.<EnergyMixDTO>map(src -> mapperEnergyMixToDTO(tariff.getEnergyMix()),
(dest, v) -> dest.setEnergyMix(v)));
}
return modelMapper.map(tariff, TariffDTO.class);
public EnergyMixDTO mapperEnergyMixToDTO(EnergyMix energyMix) {
ModelMapper modelMapper = new ModelMapper();
return modelMapper.map(energyMix, EnergyMixDTO.class);
}
这些代码块给了我预期的输出。我不需要在 ModelMapper 中包含
id
的映射。
当我尝试使用 MapStruct 时,我需要创建一个接口并为每个属性添加映射,如下所示
@Mapping(source = "id", target = "id")
// I want to add EnergyMix to EnergyMixDTO too
TariffDTO mapperTariffToDTO(Tariff tariff);
我的第一个问题,有没有办法避免 MapStruct 中的样板代码?我的意思是,如果我可以避免为相同的属性名称添加映射。另一方面,我需要为
EnergyMix
到 EnergyMixDTO
创建一个映射器,并且我可能需要在项目中的不同类中使用它。因此,我想为 EnergyMix
到 EnergyMixDTO
映射器创建另一个类,并在 Tariff
到 TariffDTO
映射器中使用它。这可能吗?
就您而言,您需要 2 个映射器:
EnergyMixMapper:
@Mapper(componentModel = MappingConstants.ComponentModel.SPRING, injectionStrategy = InjectionStrategy.CONSTRUCTOR)
public interface EnergyMixMapper {
EnergyMixDto toDto(EnergyMix entity);
}
关税映射器:
@Mapper(componentModel = MappingConstants.ComponentModel.SPRING,
injectionStrategy = InjectionStrategy.CONSTRUCTOR,
uses = { EnergyMixMapper.class })
public interface TariffMapper {
TariffDto toDto(Tariff entity);
}
这就是您所需要的!正如您所看到的,如果实体和 dto 具有相同的字段名称,那么非常简单,无需样板代码。
两个映射器的实现将是:
EnergyMixMapperImpl:
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2024-02-01T18:48:14+0100",
comments = "version: 1.5.5.Final, compiler: Eclipse JDT (IDE) 3.36.0.v20231114-0937, environment: Java 17.0.5 (Eclipse Adoptium)"
)
@Component
public class EnergyMixMapperImpl implements EnergyMixMapper {
@Override
public EnergyMixDto toDto(EnergyMix entity) {
if ( entity == null ) {
return null;
}
EnergyMixDto.EnergyMixDtoBuilder<?, ?> energyMixDto = EnergyMixDto.builder();
energyMixDto.fieldA( entity.getFieldA() );
energyMixDto.fieldB( entity.getFieldB() );
energyMixDto.id( entity.getId() );
return energyMixDto.build();
}
}
TariffMapperImpl:
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2024-02-01T18:48:14+0100",
comments = "version: 1.5.5.Final, compiler: Eclipse JDT (IDE) 3.36.0.v20231114-0937, environment: Java 17.0.5 (Eclipse Adoptium)"
)
@Component
public class TariffMapperImpl implements TariffMapper {
private final EnergyMixMapper energyMixMapper;
@Autowired
public TariffMapperImpl(EnergyMixMapper energyMixMapper) {
this.energyMixMapper = energyMixMapper;
}
@Override
public TariffDto toDto(Tariff entity) {
if ( entity == null ) {
return null;
}
TariffDto.TariffDtoBuilder<?, ?> tariffDto = TariffDto.builder();
tariffDto.energyMix( energyMixMapper.toDto( entity.getEnergyMix() ) );
tariffDto.id( entity.getId() );
return tariffDto.build();
}
}