Spring Data, REST and ManyToMany relationship



我想知道创建、记录(招摇)和公开涉及多对多关系的 REST API 的好做法是什么。一个简单的例子 -Student,"拥有"方面:

@Entity
public class Student {
private int id;
private String name;
private Set<Course> courses;
...
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
public Set<Course> getCourses() {
return courses;
}
public void setCourses(Set<Course> courses) {
this.courses = courses;
}
...
}

Course(学生甚至没有暴露):

@Entity
public class Course {
private int id;
private String name;
...
}

这将生成 3 个数据库表 - 学生、课程和关系表(H2/休眠)。让我们找一个现有的学生:

GET /api/students/1 HTTP/1.1
...
{
"id": 1,
"name": "John Smith",
"courses": [
{
"id": 2,
"name": "Maths"
},
{
"id": 1,
"name": "Java Programming"
}
]
}

好。现在,我想创建一个具有 POST 请求的新学生,该学生已注册两个现有课程:

curl -X POST 
http://localhost:8080/api/students 
-H 'postman-token: 706c8d0e-eca5-7bff-c557-3e199e8a0c17' 
-d '{
"name": "Peter Brown",
"courses": [
{
"id": 1,
"name": "Maths"
},
{
"id": 2,
"name": "Java Programming"
}
]
}'

在服务器端,这可能会触发映射方法,例如:

@ApiOperation("Creates a new student.")
@RequestMapping(method = RequestMethod.POST, 
value = "/api/students",
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Student> createStudent(@RequestBody Student student) {
Student newStudent = studentRepository.save(student);
URI location = ServletUriComponentsBuilder.fromCurrentRequest()
.path("/api/students/{id}").buildAndExpand(newStudent.getId())
.toUri();
return ResponseEntity.created(location).body(newStudent);
}

学生存储库是一个CrudRepository

问题:这将触发以下错误:

传递给持久化的分离实体:xxx.domain.Course;嵌套异常 is org.hibernate.PersistentObjectException: detached entity 传递给 坚持: xxx.domain.Course

原因:现有课程上的 ID-s(它们存在于数据库中),这使得它们"分离"。我应该如何处理这些情况?

通过创建学生并稍后通过 REST 更新它? 用特殊的逻辑进入控制器? 通过更改CascadeType

谢谢!

更新:我已经按照接受的答案中的建议将学生视为DTO,并且我还为课程引入了PATCH/GET方法。

我相信您应该将@RequestBody Student视为 dto(实际上是这样)不要直接保存它,最好提取它,创建实体或从存储库中检索它们并构建您的最终 Student 实体并将其保存到数据库中。

最新更新