java - Hibernate 多对多级联删除

标签 java sql hibernate annotations many-to-many

我的数据库中有 3 个表:StudentsCoursesStudents_Courses

学生可以有多个类(class),类(class)可以有多个学生。 StudentsCourses 之间存在多对多的关系。

我的 Courses 表中添加了我的项目和类(class)的 3 个案例。

  • (a) 当我添加一个用户时,它会被很好地保存,
  • (b) 当我为学生添加类(class)时,它会在 User_Courses 中创建新行——这也是预期的行为。
  • (c) 当我试图删除学生时,它会删除 StudentsStudents_Courses 中的相应记录,但同时也会删除 Courses 记录不是必需的。即使我在类(class)中没有任何用户,我也希望类(class)在那里。

下面是我的表格和注释类代码。

    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 测试证实:

  • 我可以完美地向学生添加类(class),反之亦然
  • 如果我从学生那里删除类(class),该类(class)不会被删除
  • 反之亦然
  • 如果我删除了一个学生,所有类(class)都会被分离,但它们仍会(对其他学生)保留在数据库中
  • 反之亦然

关于java - Hibernate 多对多级联删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14585836/

相关文章:

java - ZoneIds 在其他平台上的可用性

java - 如何操作 JavaFX 应用程序中的所有 Activity 线程

java - 在 Spring Security 中列出内存中的用户?

mysql - 选择过滤条件及其计数

mysql - 简单的 hibernate 不起作用,但级联查询可以

java - Spring MVC - session 验证的正确方法

sql - 带有 WHERE 子句的 PostgreSQL Upsert

sql - Hive 无法在 hbase 中为外部表创建分区列

java - 事务暂停在 Spring 中如何工作?

java - Spring JPA 保存 transient 实体