我在 Spring 中使用 DTO,在 Controller
类的方法的 @RequestBody 中反序列化时遇到使用
基于接口的投影 DTO的问题。
看起来使用基于投影的 DTO 只能在一个方向上起作用。从存储库获取 DTO 非常简单方便:
public interface ConditionRepository extends JpaRepository<Condition, Long> {
@Query("SELECT c FROM Condition c WHERE c.controller.id = ?1")
List<ConditionDto> findAllByControllerId(Long controllerId);
}
但是如果 Spring 尝试在 Controller 类中反序列化基于 DTO 的相同投影
ConditionDto
@RequestMapping(value = "/{id}/conditions", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.PUT)
public ResponseEntity<List<ConditionResult>> putConditions(@RequestBody List<ConditionDto> conditionList, @PathVariable("id") Long controllerId) {
System.out.print("conditionList: ");
System.out.println(conditionList);
return null;
}
它抛出一个错误:
Type definition error: [simple type, class dev.smarthome.weatherstation.condition.dto.ConditionDto];
nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
Cannot construct instance of `dev.smarthome.weatherstation.condition.dto.ConditionDto`
(no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types,
have custom deserializer, or contain additional type information
错误是有道理的,因为 DTO 是一个接口,因此 Spring 无法实例化它。
什么是好的解决方案?我是否必须将我的实现从基于投影的 DTO 转换为类 DTO,以便它可以实例化 DTO?还是我忘记了什么?
提前感谢您的帮助!
您可以做的是编写自己的 HttpMessageConverter 并在其中创建接口的新匿名实例(基本上是手动反序列化 JSON 并将相应的字段放入 getter 中)。但我不推荐它。
相反,问问自己:为什么这个 Dto 是一个接口?在投影的情况下,它是有道理的,但投影意味着读,而不是写。
看来你有两个解决方案