具有抽象类/继承的Spring Data Rest信息库 [英] Spring Data Rest Repository with abstract class / inheritance

查看:205
本文介绍了具有抽象类/继承的Spring Data Rest信息库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法通过类继承工作获得Spring Data Rest.

I can't get Spring Data Rest with class inheritance working.

我想拥有一个可以处理所有具体类的JSON端点.

I'd like to have a single JSON Endpoint which handles all my concrete classes.

public interface AbstractFooRepo extends KeyValueRepository<AbstractFoo, String> {}

抽象类:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
  @JsonSubTypes.Type(value = MyFoo.class, name = "MY_FOO")
})
public abstract class AbstractFoo {
  @Id public String id;
  public String type;
}

具体类别:

public class MyFoo extends AbstractFoo { }

现在,当用{"type":"MY_FOO"}调用POST /abstractFoos时,它会告诉我:java.lang.IllegalArgumentException: PersistentEntity must not be null!.

Now when calling POST /abstractFoos with {"type":"MY_FOO"}, it tells me: java.lang.IllegalArgumentException: PersistentEntity must not be null!.

这似乎发生了,因为Spring不了解MyFoo.

This seems to happen, because Spring doesn't know about MyFoo.

是否有某种方法可以在不为其创建存储库和REST端点的情况下向Spring Data REST提供有关MyFoo的信息?

Is there some way to tell Spring Data REST about MyFoo without creating a Repository and a REST Endpoint for it?

(我正在使用Spring Boot 1.5.1和Spring Data REST 2.6.0)

(I'm using Spring Boot 1.5.1 and Spring Data REST 2.6.0)

Application.java:

Application.java:

@SpringBootApplication
@EnableMapRepositories
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
  }
}

推荐答案

我正在使用Spring Boot 1.5.1和Spring Data Release Ingalls.

I'm using Spring Boot 1.5.1 and Spring Data Release Ingalls.

KeyValueRepository不适用于继承.它使用每个已保存对象的类名来查找对应的键值存储.例如. save(new Foo())会将保存的对象放置在Foo集合内.并且abstractFoosRepo.findAll()将在AbstractFoo集合中查找,并且找不到任何Foo对象.

KeyValueRepository doesn't work with inheritance. It uses the class name of every saved object to find the corresponding key-value-store. E.g. save(new Foo()) will place the saved object within the Foo collection. And abstractFoosRepo.findAll() will look within the AbstractFoo collection and won't find any Foo object.

以下是使用MongoRepository的工作代码:

默认的Spring Boot应用程序启动器.

Default Spring Boot Application Starter.

@SpringBootApplication
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

AbstractFoo.java

  • 我已经测试了include = JsonTypeInfo.As.EXISTING_PROPERTYinclude = JsonTypeInfo.As.PROPERTY.两者似乎都可以正常工作!

    AbstractFoo.java

    • I've tested include = JsonTypeInfo.As.EXISTING_PROPERTY and include = JsonTypeInfo.As.PROPERTY. Both seem to work fine!

      甚至可以使用自定义的JacksonModule注册Jackson子类型.

      It's even possible to register the Jackson SubTypes with a custom JacksonModule.

      重要提示:强烈建议@RestResource(path="abstractFoos").否则,_links.self链接将指向/foos/bars而不是/abstractFoos.

      IMPORTANT: @RestResource(path="abstractFoos") is highly recommended. Else the _links.self links will point to /foos and /bars instead of /abstractFoos.

      @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
      @JsonSubTypes({
        @JsonSubTypes.Type(value = Foo.class, name = "MY_FOO"),
        @JsonSubTypes.Type(value = Bar.class, name = "MY_Bar")
      })
      @Document(collection="foo_collection")
      @RestResource(path="abstractFoos")
      public abstract class AbstractFoo {
        @Id public String id;
        public abstract String getType();
      }
      

      AbstractFooRepo.java

      这里没什么特别的

      AbstractFooRepo.java

      Nothing special here

      public interface AbstractFooRepo extends MongoRepository<AbstractFoo, String> { }
      

      Foo.java& Bar.java

      @Persistent
      public class Foo extends AbstractFoo {
        @Override
        public String getType() {
          return "MY_FOO";
        }
      }
      
      @Persistent
      public class Bar extends AbstractFoo {
        @Override
        public String getType() {
          return "MY_BAR";
        }
      }
      

      FooRelProvider.java

      • 没有这部分,对象的输出将在_embedded.foos_embedded.bars下分成两个数组.
      • supports方法可确保对于所有扩展AbstractFoo的类,将对象放置在_embedded.abstractFoos中.
      • FooRelProvider.java

        • Without this part, the output of the objects would be separated in two arrays under _embedded.foos and _embedded.bars.
        • The supports method ensures that for all classes which extend AbstractFoo, the objects will be placed within _embedded.abstractFoos.
        • @Component
          @Order(Ordered.HIGHEST_PRECEDENCE)
          public class FooRelProvider extends EvoInflectorRelProvider {
            @Override
            public String getCollectionResourceRelFor(final Class<?> type) {
              return super.getCollectionResourceRelFor(AbstractFoo.class);
            }
          
            @Override
            public String getItemResourceRelFor(final Class<?> type) {
              return super.getItemResourceRelFor(AbstractFoo.class);
            }
          
            @Override
            public boolean supports(final Class<?> delimiter) {
              return AbstractFoo.class.isAssignableFrom(delimiter);
            }
          }
          


          编辑

          • Foo.javaBar.java中添加了@Persistent. (将其添加到AbstractFoo.java不起作用).如果没有此注释,则在尝试在继承的类中使用JSR 303验证注释时,会出现NullPointerExceptions.

          • EDIT

            • Added @Persistent to Foo.java and Bar.java. (Adding it to AbstractFoo.java doesn't work). Without this annotation I got NullPointerExceptions when trying to use JSR 303 Validation Annotations within inherited classes.
            • 重现该错误的示例代码:

              Example code to reproduce the error:

              public class A {
                @Id public String id;
                @Valid public B b;
              
                // @JsonTypeInfo + @JsonSubTypes
                public static abstract class B {
                  @NotNull public String s;
                }
              
                // @Persistent <- Needed!
                public static class B1 extends B { }
              }
              

              这篇关于具有抽象类/继承的Spring Data Rest信息库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆