cascade.Persist in @ManyToMany 一般情况下它是如何工作的以及在这种情况下它是如何工作的

问题描述 投票:0回答:1

我有2个实体,一个是学生,另一个是课程。它们以多对多双向方式相互连接。我正在执行如下代码所示的操作。

@NoArgsConstructor
@AllArgsConstructor
@Entity
@SuperBuilder
@Table(name = "_student")
@DiscriminatorValue("ent_Student")
public class Student extends User{
    
      @JsonIgnore   
      @ManyToMany(cascade = {
                CascadeType.PERSIST,
                CascadeType.MERGE
            })
            @JoinTable(name = "students_courses",
                joinColumns = @JoinColumn(name = "student_id"),
                inverseJoinColumns = @JoinColumn(name = "course_id")
      )
      private Set<Course> courses;

      
      
    public Set<Course> getCourses() {
        if(courses == null) {
            courses = new HashSet<Course>();
        }
        return courses;
    }

    public void setCourses(Set<Course> courses) {
        this.courses = courses;
    }
      
      



}
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "_course")
public class Course {
    
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      public Integer id;

      @Column(unique = true)
      public String courseName;
      
      @JsonIgnore
      @ManyToMany(mappedBy = "courses")
      public Set<Student> students;

//getter setters
}

我有这样的@Service方法

    public AssignCourseToStudentResponse assignCourseToStudent2(Integer id,Integer id2) {
        
        AssignCourseToStudentResponse resp;
        
        Optional<Student> st = student_Repo.findById(id);
        
        Optional<Course> course = course_repo.findById(id2);
    
        Student s = st.orElseThrow();
        
        s.getCourses().add(course.get());
        
        student_Repo.save(st.get());
        
        Optional<Course> courseDebug = course_repo.findById(id2);
        
        Iterator<Student> it= courseDebug.get().students.iterator();
        
        while(it.hasNext()) {
            System.out.println(it.next());
            if(it.hasNext() == false) {
                break;
            }
        }
        
        resp = AssignCourseToStudentResponse.builder().message(ResponseMessage.SUCCESSFUL).build();
        
        return resp;
    } 

当我执行上面服务部分中编写的代码时

它已按我的预期添加到表中。

但我真正的问题是,如果我从学生中删除cascade.persist,它会像以前一样将学生和课程添加到中间表中,并在它们之间创建关系。

那么,这种情况下persist的目的是什么,hibernate在后台做了什么?我的另一个问题是,我刚刚将一门课程添加到学生对象中,当我直接保存学生时,我可以从课程实体访问我的学生对象,当我仅保存学生对象时,我的学生是如何添加到课程对象中的学生集合?这不是级联的情况吗?或者在这种情况下休眠是如何工作的?我正在努力学习软件。您能更详细地解释一下吗?谢谢你

我没想到当cascade.persist不存在时数据会被添加到中间表中

java hibernate cascade persist
1个回答
0
投票

cascade
注释中的
@ManyToMany
属性是一个配置选项,允许将级联属性中指定的操作应用于两个关联的实体。换句话说,对您的实体进行的操作也将在关系的另一方进行。

CascadeType.PERSIST
意味着如果我们保存
Student
实体,那么所有
Course
实体也应该被保存。此级联操作从
Student
对象流向相关的
Course
对象。但是,由于
Student
Course
之间的关系是在单独的关联表 (
students_courses
) 中管理的,因此
CascadeType.Persist
@ManyToMany
的上下文中没有任何意义。

这是因为

Course
实体并非真正由设置中的
Student
实体“拥有”。它们独立存在,并且只是相关联的。添加
Course
并不意味着在数据库中保存新的
Course

当您执行

s.getCourses().add(course.get());
并使用
student_Repo.save(st.get());
保存学生时,您实际上并未保留新的
Course
,而是标记了现有
Student
Course
之间的关联,这反映在连接表(
students_courses
).

现在,如果您检查

Course
实体,您就能够获取关联的
Student
,因为您使用
Course
再次从数据库中获取了
course_repo.findById(id2);
。然后,Hibernate 也会从
students_courses
中获取关系,当您将
Course
添加到
Student
中时,该关系已被更新。

总之,

Cascade.Persist
ManyToMany
关系的上下文中没有什么意义,因为持久化实体并不意味着持久化关系,并且添加的课程是关联实体,而不是
Student
的直接部分。当您保存
Student
时,关系的实际持久性就会发生。

当您在

students_courses
上调用
save()
时,Hibernate 会通过将关联保存在
Student
表中来处理此问题,并在您检索
Course
时获取关联,给人一种错觉,就好像它已被级联一样。

记住,

CascadeType.PERSIST
@OneToMany
@OneToOne
关系中更为重要,在这些关系中,持久化实体可能需要持久化其子/后代。在
@ManyToMany
关系中,它不会持久化关联实体,只是在连接表中标记它们的关联。

我希望这有助于澄清概念!

© www.soinside.com 2019 - 2024. All rights reserved.