TL; DR
Я хочу использовать modelMapper таким образом, чтобы я отображал из AbstractParent в AbstractParentDTO, а затем в ModelMapper-Config вызывал конкретные преобразователи для каждого подкласса изатем пропустите остальные сопоставления (класса abstrac).
Как это возможно?Это правильный подход?Есть ли недостатки дизайна?
Что у меня есть:
Родительский объект:
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "type")
public abstract class Parent {
//some more fields
}
Один дочерний объект:
//Basic Lombok Annotations
@DiscriminatorValue("child_a")
public class ChildA extends Parent {
//some more fields
}
Другая дочерняя сущность:
@DiscriminatorValue("child_b")
public class ChildB extends Parent {
//some more fields
}
Тогда у меня есть родительский класс DTO:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
@JsonSubTypes({
@JsonSubTypes.Type(value = ChildA.class, name = "child_a"),
@JsonSubTypes.Type(value = ChildB.class, name = "child_b"),
public abstract class ParentDTO {
//some more fields
}
Один дочерний DTO:
public class ClassADTO extends ParentDTO {
//some more fields
}
и другое DTO:
public class ClassBDTO extends ParentDTO {
//some more fields
}
В моем случае я получу DTO от контроллера и сопоставлю их с сущностями при передаче их Сервису.Мне придется делать то же самое в 5-6 конечных точках.
Конечные точки выглядят примерно так:
@PreAuthorize(CAN_WRITE)
@PutMapping("/{id}")
public ResponseEntity<ParentDTO> update(
@PathVariable("id") UUID id,
@RequestBody @Valid ParentDTO parentDTO) {
Parent parent = parentService.update(id, parentDTO);
if (parentDTO instanceof ChildADTO) {
return ResponseEntity.ok(modelMapper.map(parent, ChildADTO.class));
} else if (parentDTO instanceof ChildBDTO) {
return ResponseEntity.ok(modelMapper.map(parent, ChildBDTO.class));
}
throw new BadRequestException("The Parent is not Valid");
}
Только у меня есть еще несколько детей, которые делают вещи еще громоздче.
То, что я хочу:
Вместо того, чтобы много раз проверять, что такое экземпляр DTO (или Entity), я просто хочу написать, например,:
modelmapper.map(parent, ParentDTO.class)
и выполните проверку "экземпляр ..." РАЗ в моей конфигурации ModelMapper.
Что я пробовал:
У меня уже есть разные конвертеры для каждого возможного направления и случая отображения, определенных в моей конфигурации ModelMapper (поскольку они в любом случае требуют более сложного отображения).
Я попытался решить свою проблему, написав еще одинКонвертер для родительских классов и установка его в качестве преконвертера ModelMapper:
//from Entity to DTO
Converter<Parent, ParentDTO> parentParentDTOConverter = mappingContext -> {
Parent source = mappingContext.getSource();
ParentDTO dest = mappingContext.getDestination();
if (source instanceof CHildA) {
return modelMapper.map(dest, ChildADTO.class);
} else if (source instanceof ChildB) {
return modelMapper.map(dest, ChildBDTO.class);
}
return null;
};
и:
modelMapper.createTypeMap(Parent.class, ParentDTO.class)
.setPreConverter(parentParentDTOConverter);
Но я всегда получаю одну и ту же ошибку MappingError:
1) Не удалось создать экземпляр экземпляра назначения com.myexample.data.dto.ParentDTO.Убедитесь, что com.myexample.data.dto.ParentDTOO имеет частный конструктор без аргументов.
, который я получаю (я полагаю), я не могу создать объект абстрактного класса.Но это не то, что я пытаюсь?Я предполагаю, что modelMapper все еще выполняет остальную часть Mapping после окончания моего PreConverter.Я также пытался установить его с помощью .setConverter, но всегда с тем же результатом.
Кто-нибудь знает, как «отключить» пользовательские сопоставления?Я действительно не хочу писать «псевдо-картографы», которые действуют как картографы и просто вызывают определенные картографы для каждого сценария.
Мой дизайн просто плох?Как бы вы улучшили его?
Это просто еще не реализовано в ModelMapper?
Любая помощь и подсказка приветствуется.