[英]Spring Data, REST and ManyToMany relationship
I wonder what is a good practice to create, document (swagger) and expose REST API involving many-to-many relationships. 我想知道创建,记录(混乱)和公开涉及多对多关系的REST API的良好做法是什么? A simple example -
Student
, the 'owning' side: 一个简单的例子
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;
}
...
}
And Course
(the students are not even exposed): 和
Course
(学生甚至没有暴露):
@Entity
public class Course {
private int id;
private String name;
...
}
This results in 3 DB tables - students, courses and relation table (H2/hibernate). 这将产生3个DB表-学生,课程和关系表(H2 /休眠)。 Let's get an existing student:
让我们找一个现有的学生:
GET /api/students/1 HTTP/1.1
...
{
"id": 1,
"name": "John Smith",
"courses": [
{
"id": 2,
"name": "Maths"
},
{
"id": 1,
"name": "Java Programming"
}
]
}
Fine. 精细。 Now I would like to create a new student with POST request who is enrolled into two existing courses:
现在,我想用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"
}
]
}'
On server side this may trigger a mapped method, eg: 在服务器端,这可能会触发映射方法,例如:
@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);
}
The student repository is a CrudRepository
. 学生存储库是
CrudRepository
。
Problem : This will trigger the following error: 问题 :这将触发以下错误:
detached entity passed to persist: xxx.domain.Course;
传递给持久性的独立实体:xxx.domain.Course; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: xxx.domain.Course
嵌套的异常是org.hibernate.PersistentObjectException:分离的实体传递给持久化:xxx.domain.Course
Cause: the ID-s on the existing courses (they exist in DB) which makes them "detached". 原因:现有课程的ID(它们在DB中存在)使它们“分离”。 How should I handle these situations?
我应该如何处理这些情况?
By creating a student and later updating it via REST? 通过创建学生并随后通过REST更新它? With a special logic into the controller?
带有特殊逻辑的控制器? By changing the
CascadeType
? 通过更改
CascadeType
?
Thanks! 谢谢!
UPDATE: I've treated the Student as DTO as suggested in the accepted answer and I've also introduced a PATCH/GET method for the courses. 更新:我已经按照接受的答案中的建议将学生视为DTO,并且还为课程引入了PATCH / GET方法。
我相信您应该将@RequestBody Student
视为dto(实际上是),不要直接保存它,最好将其提取,创建实体或从存储库中检索它们,并构建最终的Student实体并将其保存到数据库。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.