TL; DR
我想以一种从AbstractP的映射方式来使用ModelMapper,然后在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个endpoint做同样的事情。
endpoint大致如下所示:
@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配置中定义的每个可能的方向和映射案例提供了不同的转换器(因为它们无论如何都需要更复杂的映射)。
我试图通过为父类编写一个转换器并将其设置为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);
但我总是遇到同样的映射错误:
1) 未能实例化目标com的实例。我举个例子。数据dto。父母。确保com。我举个例子。数据dto。ParentDTOO有一个非私有的无参数构造函数。
我得到(我猜),我不能构造抽象类的对象。但那不是我想要的,是吗?我猜modelMapper在完成我的预转换后仍在进行其余的映射。我也试着把它设置为。设置转换器,但始终具有相同的结果。
>
有人知道如何禁用自定义映射吗?我真的不想写“伪映射器”,它们像映射器一样,只是为每个场景调用特定的映射器。
我的设计很糟糕吗?你将如何改进它?
这还没有实现到ModelMapper中吗?
任何帮助和暗示都将不胜感激。
怎么样
TypeMap<Parent.class, ParentDTO.class> typeMap = modelMapper.createTypeMap(Parent.class, ParentDTO.class);
typeMap
.include(ChildA .class, ClassADTO .class)
.include(ChildB.class, ClassbDTO.class);
参考:http://modelmapper.org/user-manual/type-map-inheritance
嗯,我找到的解决方案使用转换器。在本例中,modelMapper
不尝试创建抽象类的新实例,而是直接使用转换器。
您可以将所有转换器放在同一个位置
modelMapper.createTypeMap(ChildA.class, ParentDTO.class)
.setConverter(mappingContext -> modelMapper.map(mappingContext.getSource(), ClassADTO.class));
modelMapper.createTypeMap(ChildB.class, ParentDTO.class)
.setConverter(mappingContext -> modelMapper.map(mappingContext.getSource(), ClassBDTO.class));
....
在父类中添加获取鉴别器值的可能性。
//..
public class Parent {
@Column(name = "type", insertable = false, updatable = false)
private String type;
//getters and setters
}
您的ParentDTO应映射到子(*)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);
通过这种方式,您的父母DTO总是使用正确的类型实例化。
我有一个C#类 产品有名称、价格等属性 我想要一个linq查询,它将返回带有产品数组的产品类别的结构,但仅当产品的属性等于一个值时。例如价格是10的地方。 我试过了 但这返回给我一个产品数组,但我想要产品类别中所有符合条件的产品。 作为一个额外的挑战,我也有多个标准,所以在这个例子中,假设价格等于10,30和50。其中一个标准有两个值,这就增加了复杂性。我要做的只是调用不同的选择标准,然后在结尾处
我有一个样式规则,当一个标记有两个类时,我想应用于它。在没有JavaScript的情况下,有什么方法可以执行此操作吗?换句话说: 只有在同时应用了和类时,我才要应用我的样式规则。
让我们假设我有一个这样的结构化数组: 我将这个结构称为“categories”,所以,我在这个数组中有六个类别。我的目标是根据一个类别随机挑选一个产品。 我想做一个基于速率的类别选择,据我所知,我必须计算这个类别在数组中代表多少百分比,例如: 这会给我类似的东西: 好的,现在我要做一个简单的算法,根据这些比率得到类别;我想我现在需要在范围之间选择一个随机数,并制作一些“切片”,例如: 如果随机数介
我有这个: 我想选择类为col-md-4,6,8,12的排班的孩子。有没有什么好办法一次全选? 可以有多个行DIV,我将使用wrapAll将每个行DIV的子级包装到其他DIV中。所以如果我使用wrapAll,它只是将其他行div的所有内容转移到第一个行div。如果我将选择器查询放在循环内部,它只是继续包装子项乘以行divs的数量。我不想让这种事发生。 你们听懂了吗?
我与ModelMapper框架有麻烦。请解释为什么我看到以下行为。 我在build.gradle有以下依赖性 和一个类客户: 我还有一个地图绘制工具: 还有一个测试 在fred()中,方法输出是非红色的“Customer{name=fred,age=40}”(“Customer{name=null,age=40}”)。你能解释一下为什么吗?为什么我在第一个方法中看不到输出“George”?