POSTing a @OneToMany sub-resource association in Spring Data REST

匿名 (未验证) 提交于 2019-12-03 01:25:01

问题:

Currently I have a Spring Boot application using Spring Data REST. I have a domain entity Post which has the @OneToMany relationship to another domain entity, Comment. These classes are structured as follows:

Post.java:

@Entity public class Post {      @Id     @GeneratedValue     private long id;     private String author;     private String content;     private String title;      @OneToMany     private List 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... } 

Their Spring Data REST JPA repositories are basic implementations of CrudRepository:

PostRepository.java:

public interface PostRepository extends CrudRepository { } 

CommentRepository.java:

public interface CommentRepository extends CrudRepository { } 

The application entry point is a standard, simple Spring Boot application. Everything is configured stock.

Application.java

@Configuration @EnableJpaRepositories @Import(RepositoryRestMvcConfiguration.class) @EnableAutoConfiguration public class Application {      public static void main(final String[] args) {         SpringApplication.run(Application.class, args);     } } 

Everything appears to work correctly. When I run the application, everything appears to work correctly. I can POST a new Post object to http://localhost:8080/posts like so:

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

Result at 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"         }     } } 

However, when I perform a GET at http://localhost:8080/posts/1/comments I get an empty object {} returned, and if I try to POST a comment to the same URI, I get an HTTP 405 Method Not Allowed.

What is the correct way to create a Comment resource and associate it with this Post? I'd like to avoid POSTing directly to http://localhost:8080/comments if possible.

回答1:

You have to post the comment first and while posting the comment you can create an association posts entity.

It should look something like below :

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

and it will work perfectly fine.



回答2:

Assuming you already have discovered the post URI and thus the URI of the association resource (considered to be $association_uri in the following), it generally takes these steps:

  1. Discover the collection resource managing comments:

    curl -X GET http://localhost:8080  200 OK { _links : {     comments : { href : "…" },     posts :  { href : "…" }   } } 
  2. Follow the comments link and POST your data to the resource:

    curl -X POST -H "Content-Type: application/json" $url  { … // your payload // … }  201 Created Location: $comment_url 
  3. Assign the comment to the post by issuing a PUT to the association URI.

    curl -X PUT -H "Content-Type: text/uri-list" $association_url $comment_url  204 No Content 

Note, that in the last step, according to the specification of text/uri-list, you can submit multiple URIs identifying comments separated by a line break to assign multiple comments at once.

A few more notes on the general design decisions. A post/comments example is usually a great example for an aggregate, which means I'd avoid the back-reference from the Comment to the Post and also avoid the CommentRepository completely. If the comments don't have a lifecycle on their own (which they usually don't in an composition-style relationship) you rather get the comments rendered inline directly and the entire process of adding and removing comments can rather be dealt with by using JSON Patch. Spring Data REST has added support for that in the latest release candidate for the upcoming version 2.2.



回答3:

There are 2 types of mapping Association and Composition. In case of association we used join table concept like

Employee--1 to n-> Department

So 3 tables will be created in case of Association Employee, Department, Employee_Department

You only need to create the EmployeeRepository in you code. Apart from that mapping should be like that:

class EmployeeEntity{  @OnetoMany(CascadeType.ALL)    private List depts {     }  } 

Depatment Entity will not contain any mappping for forign key...so now when you will try the POST request for adding Employee with Department in single json request then it will be added....



回答4:

I faced the same scenario and I had to remove the repository class for the sub entity as I have used one to many mapping and pull data thru the main entity itself. Now I am getting the entire response with data.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!