带有抽象类/继承的Spring Data Rest存储库

Ben*_*n M 5 inheritance spring spring-data spring-data-rest spring-data-keyvalue

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

我想要一个JSON端点来处理我所有的具体类.

回购:

public interface AbstractFooRepo extends KeyValueRepository<AbstractFoo, String> {}
Run Code Online (Sandbox Code Playgroud)

抽象类:

@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;
}
Run Code Online (Sandbox Code Playgroud)

具体类:

public class MyFoo extends AbstractFoo { }
Run Code Online (Sandbox Code Playgroud)

现在打电话POST /abstractFoos{"type":"MY_FOO"},它告诉我:java.lang.IllegalArgumentException: PersistentEntity must not be null!.

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

有没有办法告诉Spring Data REST MyFoo而不为它创建存储库和REST端点?

(我使用的是Spring Boot 1.5.1和Spring Data REST 2.6.0)

编辑:

Application.java:

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

Ben*_*n M 6

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

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

这是使用MongoRepository的工作代码:

Application.java

默认的Spring Boot Application Starter.

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

AbstractFoo.java

  • 我测试过include = JsonTypeInfo.As.EXISTING_PROPERTYinclude = JsonTypeInfo.As.PROPERTY.两者似乎工作正常!

  • 甚至可以使用自定义JacksonModule注册Jackson SubTypes.

  • 重要提示: @RestResource(path="abstractFoos")强烈推荐.否则_links.self链接将指向/foos/bars不是/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();
}
Run Code Online (Sandbox Code Playgroud)

AbstractFooRepo.java

这里没什么特别的

public interface AbstractFooRepo extends MongoRepository<AbstractFoo, String> { }
Run Code Online (Sandbox Code Playgroud)

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";
  }
}
Run Code Online (Sandbox Code Playgroud)

FooRelProvider.java

  • 如果没有这部分,对象的输出将在_embedded.foos和下面的两个数组中分开_embedded.bars.
  • supports方法确保对于所有扩展的类AbstractFoo,将对象放置在其中_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);
  }
}
Run Code Online (Sandbox Code Playgroud)

编辑

  • 添加@PersistentFoo.javaBar.java.(添加它AbstractFoo.java不起作用).如果没有这个注释,我在尝试在继承的类中使用JSR 303验证注释时会得到NullPointerExceptions.

重现错误的示例代码:

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 { }
}
Run Code Online (Sandbox Code Playgroud)