我想知道创建,记录(swagger)和暴露涉及多对多关系的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个DB表 - 学生,课程和关系表(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
。
问题:这将触发以下错误:
传递给persist的分离实体:xxx.domain.Course;嵌套异常 是org.hibernate.PersistentObjectException:传递给的分离实体 坚持:xxx.domain.Course
原因:现有课程的ID-s(它们存在于DB中)使得他们&#34;分离&#34;。我该如何处理这些情况?
通过创建学生并稍后通过REST更新它?
有一个特殊的逻辑进入控制器?
通过更改CascadeType
?
谢谢!
更新:我已按照接受的答案建议将学生视为DTO,并且我还为课程介绍了PATCH / GET方法。
答案 0 :(得分:2)
我相信您应该将<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<center>
<p>REGISTRATION</p>
<form method="post">
<h1>Add Student</h1>
<table cellpadding="2">
<tr>
<td align="right">Student Name</td>
<td align="left"><input type="text" id="studentName" name="studentName"
size="32" required></td>
</tr>
<tr>
<td align="right">Contact No</td>
<td align="left"><input type="number" name="contactNo" id="Contact"
size="32" maxlength="10" required></td>
</tr>
<tr>
<td align="right">Gender</td>
<td align="left">
<input type="radio" name="gender" value="Male" checked>Male
<input type="radio" name="gender" value="Female">Female
</td>
</tr>
<tr>
<td align="right">Email Id</td>
<td align="left">
<input type="email" title="Enter valid acharya email" pattern="[a-zA-Z]+\.
[a-zA-Z]+\.([0-9][1-9]|[1-9][0-9])@acharya\.ac\.in" id="email" size="32"
required>
</td>
</tr>
<tr>
<td align="right">Address Line</td>
<td align="left"><textarea placeholder="Your Address Here..." rows="5"
cols="100"></textarea></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="Add" id="btn"
onclick="validate()" />
<input type="button" value="Reset" id="btn" />
</td>
</tr>
</table>
</form>
</center>
视为dto(它实际上是)不直接保存它,更好地提取它,创建实体或从存储库中检索它们并构建最终的Student实体并保存它到数据库。