【问题标题】:Can Spring Data JPA Enforce ManyToOne Relationship via @JoinColumnSpring Data JPA 可以通过@JoinColumn 强制执行多对一关系吗
【发布时间】:2020-01-26 01:08:38
【问题描述】:

我有一个使用 Spring Data REST 和 Spring Data JPA 的 Spring Boot 应用程序。我有两个域实体:学生和教室,其中许多学生可以属于同一个教室。

学生:

@Data
@Entity
@Table(name = "STUDENT")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "STUDENT_ID")
    private Integer studentId;  // This Id has been setup as auto generated in DB

    @Column(name = "ROOM_ID")
    private Integer roomId;

    @ManyToOne
    @JoinColumn(name = "ROOM_ID", nullable = false, updatable = false, insertable = false)
    private Classroom classroom;
   }

教室:

@Data
@Entity
@Table(name = "CLASSROOM")
public class Classroom {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ROOM_ID")
    private Integer roomId;  // This Id has been setup as auto generated in DB

    @OneToMany(mappedBy = "classroom")
    private List<Student> studentList;

    .....// other fields related to a classroom
  }

还有学生存储库:

public interface StudentRepository extends CrudRepository<Student , Integer>{
  List<Student> findByClassroom(@Param("room") Classroom room);
}

还有 Classroom 存储库:

public interface ClassroomRepository extends CrudRepository<Classroom , Integer>{
}

我有一个 SpringApplication 主文件,但没有控制器。

CLASSROOM 表中已有一间教室,房间 id=1。当我向http://localhost:8080/students 发出以下POST 请求时,在Student 表中创建了一个新的学生记录,我预计它会失败,因为CLASSROOM 中不存在id=100 的教室。

所以我的问题是:Spring Data JPA 可以强制执行 manyToOne 关系还是必须在数据库端执行此外键强制(Student 表中的非空 ROOM_ID 列未定义为外键 由我们的 DBA 出于合法考虑)。如果必须在数据库端完成,那么在实体文件中定义 manyToOne 关系有什么意义?

另外,我知道我在 Student 实体中有多余的教室字段,我只是不知道在 Student 实体中保留哪一个(roomId 或“教室”字段),因为当我创建一个学生时,我只想在请求中提供教室的 roomId。谢谢!

{ 
  "roomId": 100  // I expect this request to fail because no roomId=100 in the CLASSROOM table.
}

【问题讨论】:

    标签: spring-boot spring-data-jpa spring-data spring-data-rest


    【解决方案1】:

    在实体文件中定义多对一关系有什么意义

    Because 是一个对象关系映射工具,可让您定义实体图。

    您当前正在传递roomId,它在您的实体中只是另一个字段,因此您需要将其删除。

    @Entity
    @Table(name = "STUDENT")
    public class Student {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "STUDENT_ID")
        private Integer studentId;  // This Id has been setup as auto generated in DB
    
        @ManyToOne
        @JoinColumn(name = "ROOM_ID", nullable = false)
        private Classroom classroom;
    }
    

    然后,在 Spring Data Rest 中,您通过传递被引用实体的 self 链接来定义关联。

    然后您的请求需要如下所示:

    { 
      "classroom" : "http://localhost:8080/classrooms/1"
    }
    

    同时在您发布新记录时删除 ID,正如您所注意到的,ID 是在数据库中自动生成的。

    另见:

    https://www.baeldung.com/spring-data-rest-relationships

    【讨论】:

    • 谢谢。我从 Student 实体中删除了“roomId”,并且还更新了 Student 存储库(也在上面的帖子中)。但是,当我在邮递员的回答中提出请求时,我收到一个错误“无法将值 NULL 插入到列 'ROOM_ID',表 'STUDENT';列不允许空值。插入失败。”。如何通过请求提供 roomId 值?
    • 如果 http://localhost:8080/classrooms/1 返回一个教室,并且您从连接列定义中删除了 updatable = false, insertable = false,那么它应该可以工作。
    猜你喜欢
    • 2018-08-01
    • 2018-04-14
    • 2017-08-19
    • 1970-01-01
    • 1970-01-01
    • 2017-05-29
    • 1970-01-01
    • 2018-03-15
    • 1970-01-01
    相关资源
    最近更新 更多