首页 > 解决方案 > Spring Data JPA 可以通过@JoinColumn 强制执行多对一关系吗

问题描述

我有一个使用 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);
}

和课堂存储库:

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

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

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

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

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

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

标签: spring-bootspring-data-jpaspring-dataspring-data-rest

解决方案


在实体文件中定义 manyToOne 关系有什么意义

因为是一个允许您定义实体图的对象关系映射工具。

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

@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


推荐阅读