Spring DTO:无法构造<DTO interface>

问题描述 投票:0回答:1

我在 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?还是我忘记了什么?

提前感谢您的帮助!

java spring dto
1个回答
1
投票

您可以做的是编写自己的 HttpMessageConverter 并在其中创建接口的新匿名实例(基本上是手动反序列化 JSON 并将相应的字段放入 getter 中)。但我不推荐它。

相反,问问自己:为什么这个 Dto 是一个接口?在投影的情况下,它是有道理的,但投影意味着,而不是写。

看来你有两个解决方案

  • 要么创建一个新对象,它不是投影而是用于写入(HTTP POST)目的的实际对象。在这里使用正确的语义并不困难。
  • 使用虚拟对象扩展您的接口,该对象仅用于写入(HTTP POST)查询的反序列化目的。
© www.soinside.com 2019 - 2024. All rights reserved.