在 Spring Data REST 中 POSTing a@OneTomany 子资源关联

目前我有一个使用 SpringDataREST 的 SpringBoot 应用程序。我有一个域实体 Post,它与另一个域实体 Comment@OneToMany关系。这些课程的结构如下:

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...
}

注释.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> { }

Java:

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

应用程序入口点是一个标准的、简单的 SpringBoot 应用程序。

应用程序

@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 时,返回的是一个空对象 {},如果我尝试将注释发送到相同的 URI,则会得到一个 HTTP 405 Method Not Alallow。

创建 Comment资源并将其与此 Post关联的正确方法是什么?如果可能的话,我想避免直接发帖到 http://localhost:8080/comments

35025 次浏览

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.

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.

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.

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<Department> 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....

For oneToMany mapping, just make a POJO for that class you want to Map, and @OneToMany annotation to it, and internally it will map it to that Table id.

Also, you need to implement the Serializable interface to the class you are retrieving the Data.