繁体   English   中英

Spring Data,REST和ManyToMany关系

[英]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个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

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

传递给持久性的独立实体:xxx.domain.Course; 嵌套的异常是org.hibernate.PersistentObjectException:分离的实体传递给持久化:xxx.domain.Course

原因:现有课程的ID(它们在DB中存在)使它们“分离”。 我应该如何处理这些情况?

通过创建学生并随后通过REST更新它? 带有特殊逻辑的控制器? 通过更改CascadeType

谢谢!

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM