![](/img/trans.png)
[英]Why the Cascading persist does not work with many-to-many relationship in Hibernate?
[英]Hibernate many-to-many cascading delete
我的數據庫中有3個表: Students
, Courses
和Students_Courses
Courses
學生可以有多個課程,課程可以有多個學生。 Students
和Courses
之間存在多對多的關系。
我的項目有3個案例, Courses
表添加到Courses
表中。
User_Courses
創建新行 - 再次,預期的行為。 Students
和Students_Courses
Courses
的相應記錄,但它也刪除了不需要的Courses
記錄。 即使我在課程中沒有任何用戶,我也希望課程能夠在那里。 下面是我的表和注釋類的代碼。
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代碼:
@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;
}
}
我怎樣才能實現我所描述的內容? 我在網上找不到任何合理的文件。
在類似的場景中,我找到了正確的映射(並使用JUnit測試了廣泛的案例)。 我不認為我會發布測試代碼,因為這需要很長時間才能適應這個例子。 無論如何,關鍵是:
mappedBy
屬性作為注釋,使用連接列 CascadeTypes
不包括REMOVE
在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測試證實:
基於你告訴我的內容,你不希望在Student的getCourseses方法中使用cascade = CascadeType.ALL。 請記住,Hibernate級聯與數據庫級聯不同。 即使您沒有任何級聯,Hibernate也會刪除Students_Courses記錄。
考慮Hibernate級聯的最佳方法是,如果在實體上調用操作並且該操作在級聯列表中列出,則將在所有子實體上調用該操作。
例如,當您在學生上調用delete時,由於刪除位於課程的級聯列表中,因此Hibernate將在該學生引用的每個課程實體上調用delete。 這就是為什么你看到課程記錄消失的原因。
不要擔心數據庫級聯,Hibernate會自己處理這些問題。
您只需要在Student類中刪除cascade = CascadeType.ALL ,但Courses類中不需要進行任何更改
並添加以下代碼cascade = {CascadeType.PERSIST,CascadeType.MERGE,CascadeType.DETACH} ..
這意味着在刪除所有者類記錄時,它不會刪除非所有者記錄。
在此之后,在刪除時,它將僅從Student表和student_course中刪除。 課程表數據保持不變。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.