Hibernate 多对多级联删除 [英] Hibernate many-to-many cascading delete
问题描述
我的数据库中有 3 个表:Students
、Courses
和 Students_Courses
I have 3 tables in my database: Students
, Courses
and Students_Courses
学生可以有多个课程,课程可以有多个学生.Students
和 Courses
之间存在多对多关系.
Students can have multiple courses and courses can have multiple students. There is a many-to-many relationship between Students
and Courses
.
我的 Courses
表中添加了 3 个项目和课程案例.
I have 3 cases for my project and courses added to my Courses
table.
- (a) 当我添加一个用户时,它被保存得很好,
- (b) 当我为学生添加课程时,它会在
User_Courses
中创建新行 - 同样是预期行为. - (c) 当我尝试删除学生时,它会删除
Students
和Students_Courses
中的相应记录,但同时也会删除Courses
不需要的记录.即使我在课程中没有任何用户,我也希望课程在那里.
- (a) When I add a user, it gets saved fine,
- (b) When I add courses for the student, it creates new rows in
User_Courses
- again, expected behaviour. - (c) When I am trying to delete the student, it is deleting the appropriate records in
Students
andStudents_Courses
, but it is also deletingCourses
records which is not required. Even if I don't have any user in a course, I want the course to be there.
以下是我的表格和注释类代码.
Below is my code for tables and annotate classes.
CREATE TABLE `Students` (
`StudentID` INT(11) NOT NULL AUTO_INCREMENT,
`StudentName` VARCHAR(50) NOT NULL
PRIMARY KEY (`StudentID`)
)
CREATE TABLE `Courses` (
`CourseID` INT(11) NOT NULL AUTO_INCREMENT,
`CourseName` VARCHAR(50) NOT NULL
PRIMARY KEY (`CourseID`)
)
CREATE TABLE `Student_Courses` (
`StudentId` INT(10) NOT NULL DEFAULT '0',
`CourseID` INT(10) NOT NULL DEFAULT '0',
PRIMARY KEY (`StudentId`, `CourseID`),
INDEX `FK__courses` (`CourseID`),
INDEX `StudentId` (`StudentId`),
CONSTRAINT `FK__courses` FOREIGN KEY (`CourseID`) REFERENCES `courses` (`CourseID`) ON DELETE NO ACTION,
CONSTRAINT `FK_students` FOREIGN KEY (`StudentId`) REFERENCES `students` (`StudentId`)
)
这是Hibernate生成的Java代码:
This is the Java code generated by Hibernate:
@Entity
@Table(name = "Students")
public class Students implements java.io.Serializable {
private Integer StudentID;
private String Students;
private Set<Courses> Courseses = new HashSet<Courses>(0);
public Students() {
}
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "StudentID", unique = true, nullable = false)
public Integer getStudentID() {
return this.StudentID;
}
public void setStudentID(Integer StudentID) {
this.StudentID = StudentID;
}
@Column(name = "Students", nullable = false, length = 50)
public String getCampaign() {
return this.Students;
}
public void setCampaign(String Students) {
this.Students = Students;
}
@ManyToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)
@JoinTable(name = "Student_Courses", joinColumns = {
@JoinColumn(name = "StudentId", nullable = false, updatable = false)}, inverseJoinColumns = {
@JoinColumn(name = "CourseID", nullable = false, updatable = false)})
public Set<Courses> getCourseses() {
return this.Courseses;
}
public void setCourseses(Set<Courses> Courseses) {
this.Courseses = Courseses;
}
}
@Entity
@Table(name = "Courses")
public class Courses implements java.io.Serializable {
private Integer CourseID;
private String CourseName;
private Set<Students> Studentses = new HashSet<Students>(0);
public Courses() {
}
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "CourseID", unique = true, nullable = false)
public Integer getCourseID() {
return this.CourseID;
}
public void setCourseID(Integer CourseID) {
this.CourseID = CourseID;
}
@Column(name = "CourseName", nullable = false, length = 100)
public String getCourseName() {
return this.CourseName;
}
public void setCourseName(String CourseName) {
this.CourseName = CourseName;
}
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "Courseses")
public Set<Students> getStudentses() {
return this.Studentses;
}
public void setStudentses(Set<Students> Studentses) {
this.Studentses = Studentses;
}
}
我怎样才能实现我所描述的?我在网上找不到任何合理的文档.
How can I achieve what I have described? I could not find any reasonable documentation on the web.
推荐答案
我在类似的场景中找到了正确的映射(并使用 JUnit 进行了广泛的测试).我不认为我会发布测试代码,因为适应这个例子需要很长时间.无论如何,关键是:
I found the correct mapping (and tested that with JUnit with an extensive case) in a similar scenario. I don't think I am going to post testing code because it would take long time to adapt to this example. Anyway the key is to:
- 注释不使用
mappedBy
属性,使用连接列 - 列出可能的
CascadeTypes
,不包括REMOVE
- Not use
mappedBy
attribute for the annotations, use join columns - List the possible
CascadeTypes
excludingREMOVE
在 OP 的例子中
@ManyToMany(fetch = FetchType.LAZY,
cascade =
{
CascadeType.DETACH,
CascadeType.MERGE,
CascadeType.REFRESH,
CascadeType.PERSIST
},
targetEntity = Course.class)
@JoinTable(name = "XTB_STUDENTS_COURSES",
inverseJoinColumns = @JoinColumn(name = "COURSE_ID",
nullable = false,
updatable = false),
joinColumns = @JoinColumn(name = "STUDENT_ID",
nullable = false,
updatable = false),
foreignKey = @ForeignKey(ConstraintMode.CONSTRAINT),
inverseForeignKey = @ForeignKey(ConstraintMode.CONSTRAINT))
private final Set<Course> courses = new HashSet<>();
@ManyToMany(fetch = FetchType.LAZY,
cascade =
{
CascadeType.DETACH,
CascadeType.MERGE,
CascadeType.REFRESH,
CascadeType.PERSIST
},
targetEntity = Student.class)
@JoinTable(name = "XTB_STUDENTS_COURSES",
joinColumns = @JoinColumn(name = "COURSE_ID",
nullable = false,
updatable = false),
inverseJoinColumns = @JoinColumn(name = "STUDENT_ID",
nullable = false,
updatable = false),
foreignKey = @ForeignKey(ConstraintMode.CONSTRAINT),
inverseForeignKey = @ForeignKey(ConstraintMode.CONSTRAINT))
private final Set<Student> students = new HashSet<>();
广泛的 JUnit 测试证实:
Extensive JUnit testing verified that:
- 我可以完美地向学生添加课程,反之亦然
- 如果我从学生那里删除课程,该课程不会被删除
- 反之亦然
- 如果我删除一个学生,所有课程都将被分离,但它们仍然(对其他学生)保留在数据库中
- 反之亦然
这篇关于Hibernate 多对多级联删除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!