我不完全了解如何创建和访问关联资源与Spring Data REST和MongoDB一起使用。我注意到了一些奇怪的行为,我希望在这里得到一些澄清。
我有一个简单的对象模型,其中一种资源类型(Request
)包含另一种资源类型(Point
)的对象列表。这两种资源都是顶级资源,即拥有自己的Repository
接口。
我希望能够通过POST到Point
向Request
添加新的/requests/{id}/points
,其中包含指向现有点的链接(据我所知this question}我不能只将一个点作为JSON有效载荷发布。)
此外,我希望能够获取/requests/{id}/points
以检索与请求相关联的所有点。
这是我的对象模型(省略了getters / setters):
Request.java
public class Request {
@Id
private String id;
private String name;
@DBRef
private List<Point> points = new ArrayList<>();
}
RequestRepository.java
public interface RequestRepository extends MongoRepository<Request, String> {
}
Point.java
@Data
public class Point {
@Id
private String id;
private String name;
}
PointRepository.java
public interface PointRepository extends MongoRepository<Point, String> {
}
我们说我发布一个新的Request
。然后执行GET on / requests会给我这个:
{
"_links" : {
"self" : {
"href" : "http://localhost:8080/requests",
"templated" : false
}
},
"_embedded" : {
"requests" : [ {
"name" : "request 1",
"_links" : {
"self" : {
"href" : "http://localhost:8080/requests/55e5dc47b7605d55c7c361ba",
"templated" : false
},
"request" : {
"href" : "http://localhost:8080/requests/55e5dc47b7605d55c7c361ba",
"templated" : false
},
"points" : {
"href" : "http://localhost:8080/requests/55e5dc47b7605d55c7c361ba/points",
"templated" : false
}
}
} ]
}
}
所以我有一个points
链接。好。现在,如果我在/requests/55e5dc47b7605d55c7c361ba
上进行GET,我会注意到奇怪的事情#1 。再也没有points
链接:
{
"name" : "request 1",
"_links" : {
"self" : {
"href" : "http://localhost:8080/requests/55e5dc47b7605d55c7c361ba",
"templated" : false
},
"request" : {
"href" : "http://localhost:8080/requests/55e5dc47b7605d55c7c361ba",
"templated" : false
}
}
}
但是至少现在忘记了这一点,让POST点(获得ID 55e5e225b76012c2e08f1e3e
)并将其链接到请求:
curl -X PUT -H "ContentType: text/uri-list" http://localhost:8080/requests/55e5dc47b7605d55c7c361ba/points
-d "http://localhost:8080/points/55e5e225b76012c2e08f1e3e"
204 No Content
这似乎有效。好的,现在如果我在http://localhost:8080/requests/55e5dc47b7605d55c7c361ba/points
上进行GET,我希望看到我刚才添加的一点,对吧?输入奇怪的东西#2 ,我收到以下回复:
{
"_links" : {
"self" : {
"href" : "http://localhost:8080/requests/55e5dc47b7605d55c7c361ba/points",
"templated" : false
}
}
}
所以在这一点上我意识到我做错了什么。有人可以向我解释一下这里发生了什么吗?我对SDR的运作方式有根本的误解吗?我应该使用DBRef
吗?或者这对MongoDB来说根本不可能?
提前致谢,对不起这个长期问题感到抱歉!
Point
实际上被添加为DBRef
s(通过手动查看数据库进行验证),但似乎SDR没有回复它们。如果我明确要求http://localhost:8080/requests/55e5dc47b7605d55c7c361ba/points/55e5e225b76012c2e08f1e3e
,那么我得到以下回复:
{
"_links" : {
"self" : {
"href" : "http://localhost:8080/points/55e5e225b76012c2e08f1e3e",
"templated" : false
},
"point" : {
"href" : "http://localhost:8080/points/55e5e225b76012c2e08f1e3e",
"templated" : false
}
}
}
哪个也很奇怪...... Point.name
在哪里?
答案 0 :(得分:3)
这两个方面都是由glitch in Spring Framework 4.2.0引起的,Spring Boot 1.3 M4已升级到该版本导致Spring Data RESTs自定义序列化程序在某些情况下未应用。这已在Spring 4.1.2中修复。要将Gradle项目升级到该版本,请将Boot插件升级到1.3,然后使用以下声明将Spring版本修复为4.2.1:
ext['spring.version'] = '4.2.1.RELEASE'
请确保使用空值正确初始化集合,因为null
值将导致404 Not Found
返回。空列表将产生正确的HAL输出。
一般来说,关联资源应该与现有资源一起使用,尤其是使用Spring Data MongoDB,没有其他选择,因为它没有可达性的持久性。即你需要先保存相关实例(也就是。POST
到它的集合资源并获得一个Location
标题)并分配刚刚创建的资源(aka。{ {1}}或PUT
刚刚获得的关联资源位置),这似乎就是您正在做的事情。