使用Spring Data REST和MongoDB访问和更新关联资源

时间:2015-09-01 17:53:25

标签: spring spring-data spring-data-mongodb spring-data-rest spring-hateoas

我不完全了解如何创建和访问关联资源与Spring Data REST和MongoDB一起使用。我注意到了一些奇怪的行为,我希望在这里得到一些澄清。

我有一个简单的对象模型,其中一种资源类型(Request)包含另一种资源类型(Point)的对象列表。这两种资源都是顶级资源,即拥有自己的Repository接口。

我希望能够通过POST到PointRequest添加新的/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在哪里?

1 个答案:

答案 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刚刚获得的关联资源位置),这似乎就是您正在做的事情。