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

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

问题描述

我无法在类继承工作的情况下获得 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为空!.

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.

有没有办法告诉 Spring Data REST 关于 MyFoo 而无需为其创建存储库和 REST 端点?

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);
            }
          }
          

          <小时>

          编辑

          • @Persistent 添加到 Foo.javaBar.java.(将其添加到 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.
            • 重现错误的示例代码:

              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 Repository的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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