2

将 Spring Data 与 MongoDB 一起使用。

问题在于实例化从 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 获取时,如何告诉 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 ?

4

1 回答 1

4

看起来像是失礼。

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

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

spring-data-mongodb 在为对象补水时究竟是如何处理构造函数的?

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

    @PersistenceConstructor

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

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

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

        @PersistenceConstructor
        private A(int prop1, B b){
         ......
         ......
        }
于 2017-11-15T15:38:09.910 回答