MapStruct Mapper作为弹簧框架转换器 - 习惯用法可能吗?

2022-09-01 16:13:15

我想将映射器与Spring的转换模型相结合。所以我声明每个接口都是Spring的扩展:MapStructMapperConverter

@Mapper
public interface CarMapper extends Converter<Car, CarDto> {    
    @Override
    CarDto convert(Car car);    
}

然后,我可以通过注入标准来使用映射器bean:ConversionService

class CarWarehouse {
    @Autowired
    private ConversionService conversionService;

    ...

    public CarDto getCarInformation(Car car) {
        return conversionService.convert(car, CarDto.class);
    }
}

这很好用,但我想知道是否有一种方法可以避免直接通过属性将某些映射器注入其他映射器。我想做的是告诉一个映射器使用另一个映射器。但是,由于 的方法与 MapStruct 的映射方法的标准模式不匹配,因此代码生成插件无法识别在查找子映射时可以使用该服务。基本上,我想做的是写usesuseConversionServiceConversionServiceconvert

@Mapper(uses=ConversionService.class)
public interface ParentMapper extends Converter<Parent, ParentDto>

而不是

@Mapper(uses={ChildMapper1.class, ChildMapper2.class, ChildMapper3.class})
public interface ParentMapper extends Converter<Parent, ParentDto>

有没有办法做到这一点?

编辑

既然已经问过了,假设我定义了一个如上所述,类型和属性分别为 type 和 。然后,我希望能够像这样定义另一个映射器:CarMapperCarCarDtowheelWheelWheelDto

@Mapper
public interface WheelMapper extends Converter<Wheel, WheelDto> {    
    @Override
    WheelDto convert(Wheel wheel);    
}

现在,我必须显式添加此映射器:

@Mapper(uses = WheelMapper.class)
public interface CarMapper extends Converter<Car, CarDto>

然后,这将为生成的成员提供一个类型的成员,该成员将被调用以映射属性。CarMapperImpl@AutowiredWheelMapperwheel

但是,我希望生成的代码看起来有点像这样:

@Component
public class CarMapperImpl implements CarMapper {
    @Autowired
    private ConversionService conversionService;
    @Override
    public CarDto convert(Car car) {
        CarDto carDto = new CarDto();
        carDto.setWheel(conversionService.convert(car.getWheel(), WheelDto.class);
        return carDto;
    }
}

答案 1

自从我问这个问题以来已经一年多了,但现在我们已经在MapStruct项目本身中提出了一个答案 - MapStruct Spring Extensions项目。

CarMapper 示例作为项目中的示例提供。


答案 2

你可以跳过一个完全传递,当你只是有一个生成的将包含一个逻辑来映射<->以及。无需将任何内容传递给 ,使您的问题过时。WheelMapperCarMapperCarMapperImplWheelWheelDtouses

carDto.setWheel( wheelToWheelDto( car.getWheel() ) );

使用如下方法;

protected WheelDto wheelToWheelDto(Wheel wheel) {
    if ( wheel == null ) {
        return null;
    }

    WheelDto wheelDto = new WheelDto();

    wheelDto.setName( wheel.getName() );

    return wheelDto;
}

我确实尝试过实现智能注射通过,但我认为这是不可能的。你需要得到支持才能实现这样的壮举。它甚至不考虑注射 。也许已经实现并使用的自定义通用映射器可能会起作用,但我无法做到这一点!虽然我看不出任何理由,因为已经从父映射器创建了所有必要的小型映射器...ConversionServiceMapStructMapStructConversionServiceConversionServiceMapStruct


推荐