我有3代表在我的数据库:Students
,Courses
和Students_Courses
学生可以有多种课程和课程可以有多个学生。有Students
和Courses
之间的许多一对多的关系。
我有三种情况:我的项目,并添加到我的Courses
表的课程。
User_Courses
新行 - 再次,预期的行为。Students
和Students_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测试证实:
基于你告诉我你不想级联= CascadeType.ALL对学生的getCourseses方法。请记住,Hibernate的级联是不一样的数据库级联。即使你没有任何级联,则Hibernate将删除Students_Courses记录。
想Hibernate的级联的最好的办法是,如果你调用一个实体的操作和操作级联列表中列出则该操作将在所有子实体的调用。
例如,当你调用删除学生,因为删除是在课程级联列表,Hibernate会删除每个由学生引用的课程实体。这就是为什么你看到的病程记录消失。
不要担心数据库的级联,Hibernate会照顾那些自身。
你只需要删除级联= CascadeType.ALL在Student类唯一没有改变是必需的课程班
并添加以下代码级联= {CascadeType.PERSIST,CascadeType.MERGE,CascadeType.DETACH} ..
这意味着同时删除所有者类记录不会删除非所有者的记录。
在此之后,在删除它只会从学生表和student_course删除。当然,表中的数据保持不变。