在Spring Data REST中发布@OneToMany子资源关联

时间:2014-08-14 15:32:15

标签: java spring spring-boot spring-data-jpa spring-data-rest

目前我有一个使用Spring Data REST的Spring Boot应用程序。我有一个域实体Post,它与另一个域实体@OneToMany具有Comment关系。这些类的结构如下:

Post.java:

@Entity
public class Post {

    @Id
    @GeneratedValue
    private long id;
    private String author;
    private String content;
    private String title;

    @OneToMany
    private List<Comment> comments;

    // Standard getters and setters...
}

Comment.java:

@Entity
public class Comment {

    @Id
    @GeneratedValue
    private long id;
    private String author;
    private String content;

    @ManyToOne
    private Post post;

    // Standard getters and setters...
}

他们的Spring Data REST JPA存储库是CrudRepository的基本实现:

PostRepository.java:

public interface PostRepository extends CrudRepository<Post, Long> { }

CommentRepository.java:

public interface CommentRepository extends CrudRepository<Comment, Long> { }

应用程序入口点是标准的简单Spring Boot应用程序。一切都是配置库存。

Application.java

@Configuration
@EnableJpaRepositories
@Import(RepositoryRestMvcConfiguration.class)
@EnableAutoConfiguration
public class Application {

    public static void main(final String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

一切似乎都能正常运作。当我运行应用程序时,一切似乎都正常工作。我可以将新的Post对象发布到http://localhost:8080/posts,如下所示:

身体: {"author":"testAuthor", "title":"test", "content":"hello world"}

http://localhost:8080/posts/1的结果:

{
    "author": "testAuthor",
    "content": "hello world",
    "title": "test",
    "_links": {
        "self": {
            "href": "http://localhost:8080/posts/1"
        },
        "comments": {
            "href": "http://localhost:8080/posts/1/comments"
        }
    }
}

但是,当我在http://localhost:8080/posts/1/comments执行GET时,我返回了一个空对象{},如果我尝试将注释POST到同一个URI,我会得到一个不允许的HTTP 405方法。

创建Comment资源并将其与此Post相关联的正确方法是什么?我希望尽可能避免直接发布到http://localhost:8080/comments

5 个答案:

答案 0 :(得分:51)

假设您已经发现了post URI,从而发现了关联资源的URI(以下被认为是$association_uri),通常会采取以下步骤:

  1. 发现管理评论的馆藏资源:

    curl -X GET http://localhost:8080
    
    200 OK
    { _links : {
        comments : { href : "…" },
        posts :  { href : "…" }
      }
    }
    
  2. 按照comments链接和POST您的数据访问资源:

    curl -X POST -H "Content-Type: application/json" $url 
    { … // your payload // … }
    
    201 Created
    Location: $comment_url
    
  3. 通过向关联URI发出PUT来将评论分配给帖子。

    curl -X PUT -H "Content-Type: text/uri-list" $association_url
    $comment_url
    
    204 No Content
    
  4. 请注意,在最后一步中,根据text/uri-list的规范,您可以提交多个URI,用于标识由换行符分隔的注释,以便一次分配多个注释。

    关于一般设计决策的更多说明。发布/评论示例通常是聚合的一个很好的示例,这意味着我将避免从CommentPost的反向引用,并完全避免CommentRepository。如果注释没有自己的生命周期(它们通常不是在组合风格的关系中),你宁可直接内联呈现注释,而是添加和删除注释的整个过程可以通过使用来处理JSON Patch。 Spring Data REST已在即将推出的2.2版本的最新候选版本中添加了support for that

答案 1 :(得分:44)

您必须先发表评论,在发布评论时,您可以创建一个关联发布实体。

它应该如下所示:

http://{server:port}/comment METHOD:POST

{"author":"abc","content":"PQROHSFHFSHOFSHOSF", "post":"http://{server:port}/post/1"}

它会完美地运作。

答案 2 :(得分:2)

有两种类型的映射关联和组合。在关联的情况下,我们使用连接表概念,如

员工 - 1到n-&gt;系

因此,如果是关联,将创建3个表 员工,部门,员工部门

您只需要在代码中创建EmployeeRepository。除此之外,映射应该是这样的:

class EmployeeEntity{

@OnetoMany(CascadeType.ALL)
   private List<Department> depts {

   }

}

Depatment Entity不会包含forign key的任何mappping ...所以现在当你在单个json请求中尝试使用Department添加Employee的POST请求时,它将被添加....

答案 3 :(得分:1)

我遇到了同样的情况,我不得不删除子实体的存储库类,因为我使用了一对多映射并通过主实体本身提取数据。现在我收到数据的整个回复。

答案 4 :(得分:0)

对于oneToMany映射,只需为要映射的类创建一个POJO,并为其添加@OneToMany批注,然后在内部将其映射到该表ID。

此外,您需要为要检索数据的类实现Serializable接口。