0

我有一个这样的模型:

public class PersonDto {

    private CarDto car;

    public CarDto getCar() {
        return car;
    }

    public void setCar(CarDto car) {
        this.car = car;
    }

    public static class CarDto {

        private String model;

        private String color;

        public String getModel() {
            return model;
        }

        public void setModel(String model) {
            this.model = model;
        }

        public String getColor() {
            return color;
        }

        public void setColor(String color) {
            this.color = color;
        }
    }
}

VO 是不可变的:

public class PersonVo {

    private final CarDto car;

    public PersonVo(CarDto car) {
        super();
        this.car = car;
    }

    public CarDto getCar() {
        return car;
    }

    public static class CarDto {

        private final String model;

        private final String color;

        public CarDto(String model, String color) {
            super();
            this.model = model;
            this.color = color;
        }

        public String getModel() {
            return model;
        }

        public String getColor() {
            return color;
        }   
    }
}

有没有一种简单的方法可以使用ModelMapperProviders 将此场景从 Dto 转换为 Vo?

我无法使用一个提供程序来解决它,PersonVo因为当我创建新对象时,我不知道如何解析CarDto...

public class PersonVoProvider implements Provider<PersonVo> {

    public PersonVo get(org.modelmapper.Provider.ProvisionRequest<PersonVo> request) {
        PersonDto source = PersonDto.class.cast(request.getSource());
        return new PersonVo(car); ????????????
    }
}
4

2 回答 2

1

要将一个实例转换为另一个不可变的实例,请按照以下步骤操作(总结:1. 创建Provider,2. 创建Converter,3. 将两者都添加到ModelMapper configuration):

  1. 首先Provider使用AbstractProvider类创建一个以避免实例化目标错误(Failed to instantiate instance of destination com.example.pregunta.PersonVo. Ensure that com.example.pregunta.PersonVo has a non-private no-argument constructor)。你Provider应该实例化你的不可变类(在你的情况下PersonVo),即使属性是最终的,具有你想要的值,因为这个实例化只是为了避免实例化错误。例如:

    Provider<PersonVo> providerVo = new AbstractProvider<PersonVo>() {
    
        @Override
        protected PersonVo get() {
            PersonVo.CarDto carDto = new PersonVo.CarDto("", "");
            PersonVo personVo = new PersonVo(carDto);
    
            return personVo;
        }
    };
    
  2. 然后你需要创建一个Converter带有源PersonDto和目标的PersonVo。用手将一个实例转换为另一个实例,如下一个示例:

    Converter<PersonDto, PersonVo> converterDtoToVo = new Converter<PersonDto, PersonVo>() {
        @Override
        public PersonVo convert(MappingContext<PersonDto, PersonVo> context) {
            PersonDto dto =  context.getSource();
    
            String color = dto.getCar().getColor();
            String model = dto.getCar().getModel();
            PersonVo.CarDto carVo = new PersonVo.CarDto(color, model);
            PersonVo vo =  new PersonVo(carVo);
    
            return vo;
        }
    };
    
  3. 最后,需要将提供者和转换器添加到您的ModelMapper实例配置中:

    ModelMapper mapper = new ModelMapper();
    mapper.getConfiguration().setProvider(providerVo);
    mapper.addConverter(converterDtoToVo);
    

测试

我已经用这个例子试过了,效果很好:

//Instances
PersonDto dto = new PersonDto();
PersonDto.CarDto carDto = new PersonDto.CarDto();
carDto.setColor("blue");
carDto.setModel("Picasso");
dto.setCar(carDto);

PersonVo vo =  mapper.map(dto, PersonVo.class);

System.out.println(vo);

输出:

PersonVo [汽车=CarDto [型号=蓝色,颜色=毕加索]]

于 2016-09-10T09:21:05.700 回答
1

该示例使用 lombok 不可变对象和使用 modelMapper 嵌套不可变对象解决了该问题

唯一的事情是我们必须将 accessLevel 设置为私有并将构造函数声明为私有以保持不变性,lombok 使用注释为我们工作。请参见下面的示例:

首先定义modelMapper设置accesLevel为private

 ModelMapper modelMapper = new ModelMapper();
    modelMapper.getConfiguration()
            .setFieldMatchingEnabled(true)
            .setFieldAccessLevel(Configuration.AccessLevel.PRIVATE);

和不可变对象:

@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Value
@Builder
public class UserDto {

    private final Long id;

    private final String uid;

    private final String description;

    private final boolean enabled;

    @Singular
    private final Set<GroupUserDto> userGroups;
}

@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder
public class GroupUserDto {

    private Long id;

    private String name;

    private String description;

    private String comments;

    private boolean enabled;
}

最后,使用 Builder 父类调用 modelMapper.map 可以正常工作。所有字段都被映射,包括嵌套的不可变 dto

UserDto dto = modelMapper.map(user,UserDto.UserDtoBuilder.class).build();
于 2018-03-16T10:55:56.193 回答