【问题标题】:Spring Boot JPA Load Many to manySpring Boot JPA 加载多对多
【发布时间】:2020-05-12 23:27:03
【问题描述】:

我有这两张桌子:

Student 
- id
- name
- List<Course>

Course
- id
- title
- List<Student>

我有一个StudentRepository 和一个CourseRepository (JpaRepository)。

当我使用以下代码加载学生时:

    fun getAll(): List<Student> {
        return studentRepository.findAll()
    }

我得到一个无限列表。

但我希望这个 JSON 输出:

[
 {
  "id":1,
  "name":"Ben"
  "course": [
   {
   "id":1,
   "title":"Math"
   },
   {
    "id":2,
    "title":"English"
   }
  ]
 }
]

我如何得到这个结果?

//编辑: 我得到一个无限列表

【问题讨论】:

  • 你能从这些对象中添加确切的代码吗?
  • 这里有2个问题:1)如何将响应转换为JSON 2)是默认的Fetch策略一个可行的选择

标签: spring hibernate kotlin spring-data hibernate-mapping


【解决方案1】:

如果你使用jackson,你可以使用@JsonBackReference(over child)和@JsonManagedReference(over parent)注解在child中生成parent的json。

如果要禁止打印关系,可以在不被序列化的字段上使用@JsonIgnore@JsonIgnoreProperties 注释。

这是Course 类的示例:

@JsonIgnoreProperties(value = { "students" })
class Course(...)

您可以找到更多示例here

【讨论】:

    【解决方案2】:

    除非您需要在两个方向上导航关系:学生->课程和课程->学生,否则您不需要在课程中使用List&lt;Student&gt;

    如果是这种情况,那么您需要注意如何导航图表:在循环中使用/打印所有学生属性(即包括课程)Hibernate 将获取数据,并在需要时触发额外查询(即课程.学生)。

    发生这种情况的情况是,每个 Class 都有一个 toString() 打印该类的所有属性:在 Students 循环中记录每次迭代以触发无限的调用链。

    【讨论】:

    • 为什么不呢?这是多对多的关系。我错过了什么吗?
    【解决方案3】:
    @Entity
    class Student {
    
        @Id
        Long id;
    
        @ManyToMany
        @JoinTable(
                name = "course_like", 
                joinColumns = @JoinColumn(name = "student_id"), 
                inverseJoinColumns = @JoinColumn(name = "course_id"))
        List<Course> likedCourses;
    
        // additional properties
        // standard constructors, getters, and setters
    }
    
    @Entity
    class Course {
    
        @Id
        Long id;
    
        @ManyToMany(mappedBy = "likedCourses")
        Set<Student> likes;
    
        // additional properties
        // standard constructors, getters, and setters
    }
    

    所有者是我们配置关系的地方,在本例中,我们将选择 Student 类。

    注意,不需要使用 @JoinTable,甚至 @JoinColumn:JPA 将生成我们的表名和列名。但是,JPA 使用的策略并不总是与我们使用的命名约定相匹配。因此可以配置表名和列名。

    在目标端,我们只需要提供映射关系的字段名称。因此,我们在 Course 类中设置 @ManyToMany 注解的 mappedBy 属性:

    【讨论】:

      猜你喜欢
      • 2020-03-29
      • 1970-01-01
      • 2019-02-26
      • 2021-08-25
      • 2018-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-24
      相关资源
      最近更新 更多