TL;DR
我想以一种从AbstractParentMap到AbstractParentDTO的方式使用modelMapper,然后在ModelMapper-Config中为每个子类调用特定的Map器,然后跳过其余的(抽象类)Map。
这怎么可能?这是正确的方法吗?有设计缺陷吗?
我拥有的:
父实体:
@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,并在将它们提供给服务时将它们Map到实体。
端点大致如下所示:
@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配置中检查一次“instance of.”。
我尝试过的:
我已经为每一个可能的方向和在ModelMapper配置中定义的Map情况使用了不同的转换器(因为它们需要更复杂的Map)。
为了解决这个问题,我为Parent Classes再写了一个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具有非私有无参数构造函数。
我得到了(我猜),我不能构造一个抽象类的Object。但这不是我正在尝试的,是吗?我猜modelMapper在完成我的PreConverter后仍然在做剩下的Mapping。我也尝试过用.setConverter设置它,但总是得到相同的结果。
- 有谁知道如何"禁用"自定义Map吗?我真的不想写“伪Map器”,它像Map器一样工作,只是为每个场景调用特定的Map器。
- 我的设计很糟糕吗?你会如何改进它?
- 这是不是还没有在ModelMapper中实现?
任何帮助和提示是赞赏。
4条答案
按热度按时间odopli941#
我找到的解决方案是使用转换器。在这种情况下,
modelMapper
不会尝试创建抽象类的新示例,而是直接使用转换器。你可以把所有的转换器在同一个地方
字符串
ndasle7k2#
我会使用ObjectMapper而不是ModelMapper。
在Parent类中添加获取函数值的可能性。
字符串
您的ParentDTO应Map到Child(*)DTO
型
在转换服务/方法中添加一个带有ignore unknown的对象Map器(忽略未在DTO类中声明的内容)
型
只需简单地调用:
型
通过这种方式,您的ParentDTO始终使用正确的类型进行示例化。
u4vypkhs3#
怎么样
字符串
参考:http://modelmapper.org/user-manual/type-map-inheritance
xu3bshqb4#
我已经创建了一个转换器,它使用Jackson注解进行继承,所以如果您正在使用Jackson并且有很多注解,您就不需要创建两次Map(一次用于Jackson,一次用于ModelMapper)。
字符串
但是我找不到一种方法来把它分配给所有的Map,当它看到
@JsonTypeInfo
时,它会自动触发。所以仍然需要手动检查基于继承的类的列表。型