具有抽象类/继承的 Spring Data Rest Repository [英] Spring Data Rest Repository with abstract class / inheritance
问题描述
我无法在类继承工作的情况下获得 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_PROPERTY
和include = JsonTypeInfo.As.PROPERTY
.两者似乎都可以正常工作!AbstractFoo.java
I've tested
include = JsonTypeInfo.As.EXISTING_PROPERTY
andinclude = 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
中.- 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 extendAbstractFoo
, the objects will be placed within_embedded.abstractFoos
.
FooRelProvider.java
@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.java
和Bar.java
.(将其添加到AbstractFoo.java
不起作用).如果没有这个注释,我在继承的类中尝试使用 JSR 303 验证注释时得到 NullPointerExceptions. - Added
@Persistent
toFoo.java
andBar.java
. (Adding it toAbstractFoo.java
doesn't work). Without this annotation I got NullPointerExceptions when trying to use JSR 303 Validation Annotations within inherited classes.
EDIT
重现错误的示例代码:
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屋!
- 如果没有这部分,对象的输出将被分隔在