【问题标题】:constructor Arguments and Spring Data De-Serialization Issue构造函数参数和 Spring 数据反序列化问题
【发布时间】:2017-11-15 12:00:38
【问题描述】:

在 MongoDB 中使用 Spring Data。

问题在于实例化从 Mongo 检索的 bean,因为构造函数有一些参数实际上位于嵌套对象内。持久性不是问题。检索是。

类结构如下,其中 B 嵌套在 A 中。A 使用其构造函数 Params 之一设置 B 实例化它。

A类

Class A{
 int prop1;
 B b; 

 @JsonCreator
 public A(  @JsonProperty int prop1, @JsonProperty  int prop2){
  this.prop1 = prop1;
  this.b = new B(prop2);
 }
}

嵌套在 A 中的 B 类

Class B(){
 int prop2;

 @JsonCreator
 public B(@JsonProperty int prop2){
  this.prop2 = prop2;
 }
}

当 REST API 以以下 Json 形式接收 Object 时:

 {"prop1":"Hello1","prop2":"Hello2"}

Spring Controller 接收到它并正确映射到 Object A。由于 Spring 默认使用 no-arg 构造函数,所以我在 arg-constructor 上使用了 jsoncreator 注解,它被添加到 MongoDB 中没有任何大惊小怪。

数据按照正确的bean结构以以下格式存储。

      {"prop1":"Hello1","b":{"prop2":"Hello2"}}

解决问题:当我尝试从 Mongo 检索时出现错误。它说:

 org.springframework.data.mapping.model.MappingException: No property prop2 
 found on entity class A to bind constructor parameter to

从 SpringData 获取对象 B 时,如何告诉 SpringData 使用包含 prop2 的对象 B? (也许那是不可能的)

我想也许再添加一个构造函数就可以了,我使用对象 B 作为构造函数参数之一,如下所示:

   public A(int prop1, B b){
       ......
       ......
   }

再添加一个构造函数适用于 ObjectMapper,但同样不适用于 SpringData。

这一次抛出了一个新的异常:

      org.springframework.data.mapping.model.MappingInstantiationException: 
      Failed to instantiate A using constructor NO_CONSTRUCTOR with 
      arguments. 

我检查了上面正在使用/未使用 List 的错误,但我尝试了两种方法并没有解决。

请注意:我使用对象 B 作为嵌套对象,因为它包含许多其他 bean 将使用的公共属性(可能是抽象类,但我需要稍后尝试,但抽象类似乎有限制)

SpringData 如何创建对象 A ?

【问题讨论】:

    标签: spring-data-mongodb mongo-jackson-mapper


    【解决方案1】:

    看起来像是失礼。

    应该在搜索中使用更好的术语。会找到正确答案的。以防万一有人遇到这个问题......

    一些搜索使我想到了以下问题:

    How exactly does spring-data-mongodb handle constructors when rehydrating objects?

    上面的问题提到了一些给我解决方案的事情。答案在于使用另一个构造函数将 SpringData 反序列化为 bean。这个构造函数需要注解:

        @PersistenceConstructor
    

    在问题的示例中,如果我使用带有此注释的第二个构造函数,则检索工作正常。

            @PersistenceConstructor
            public A(int prop1, B b){
             ......
             ......
            }
    

    所以现在,我有 2 个构造函数,一个带有 @jsoncreator,另一个带有 @PersistenceConstructor。但是要补充一点,如果您除了从 SpringData 检索之外没有其他用途,那么这个其他构造函数也可以是私有的,并且任何人都不会在代码中使用它,从而使您的业务逻辑保持完整。 因此,以下内容也将起作用:

            @PersistenceConstructor
            private A(int prop1, B b){
             ......
             ......
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-29
      • 1970-01-01
      • 2019-02-28
      • 1970-01-01
      • 1970-01-01
      • 2017-07-02
      • 1970-01-01
      • 2016-07-13
      相关资源
      最近更新 更多