ModelMapper:基于子类选择映射

我想以某种方式使用modelMapper,将其从AbstractParent映射到AbstractParentDTO,然后在ModelMapper-

Config中为每个子类调用特定的映射器,然后跳过其余的(抽象类)映射。

那怎么可能?这是正确的方法吗?有设计缺陷吗?


父实体:

@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(或实体)是什么实例:

modelmapper.map(parent, ParentDTO.class)

并在我的ModelMapper配置中检查“实例…”一次。


我已经为ModelMapper配置中定义的每个可能的方向和映射案例使用了不同的Converter(因为它们仍然需要更复杂的映射)。

我试图通过为父类再编写一个Converter并将其设置为ModelMapper PreConverter来解决问题:

    //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具有非私有的无参数构造函数。

我知道(我猜),我无法构造一个抽象类的对象。但这不是我要尝试的,是吗?我猜想在完成我的PreConverter之后,modelMapper仍在进行其余的映射。我也尝试使用.setConverter进行设置,但始终具有相同的结果。


  • 有谁知道如何“禁用”自定义映射?我真的不想写像映射器那样的“伪映射器”,而只是为每种情况调用特定的映射器。

  • 我的设计不好吗?您将如何改善?

  • 这是否尚未在ModelMapper中实现?

任何帮助和提示表示赞赏。

回答:

我将使用ObjectMapper而不是ModelMapper。

在 类中,添加获取鉴别值的可能性。

//..

public class Parent {

@Column(name = "type", insertable = false, updatable = false)

private String type;

//getters and setters

}

您的ParentDTO应该映射到Child(*)DTO

@JsonTypeInfo(

use = JsonTypeInfo.Id.NAME,

include = JsonTypeInfo.As.PROPERTY,

property = "type")

@JsonSubTypes({

@JsonSubTypes.Type(value = ChildADTO.class, name = "child_a"),

@JsonSubTypes.Type(value = ChildBDTO.class, name = "child_b")

})

public abstract class ParentDTO {

// ..

}

在转换服务/方法中,添加一个对象忽略未知的映射器(忽略您未在DTO类中声明的内容)

    ObjectMapper objectMapper = new ObjectMapper();

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

只需调用:

Parent parent = // get from repository

ParentDTO parentDTO = objectMapper.readValue(objectMapper.writeValueAsBytes(parent), ParentDTO.class);

这样,您的ParentDTO总是用正确的类型实例化。

以上是 ModelMapper:基于子类选择映射 的全部内容, 来源链接: utcz.com/qa/410536.html

回到顶部