欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JPA之级联关系@OneToMany 和 @ManyToMany

程序员文章站 2022-04-12 20:28:31
...

JPA之级联关系@OneToMany 和 @ManyToMany

1. 双向@OneToMany

@Entity
@Table(name = "TEACHER")
public class Teacher {

    @Id
    @GenericGenerator(name = "jpa-uuid", strategy = "uuid")
    @GeneratedValue(generator = "jpa-uuid")
    @Column(name = "teacher_id")
    private String teacherId;
	
    // Teacher oneToMany Student
    // 当删除Teacher,会级联删除该Teacher的所有Student
    // 拥有mappedBy注解的实体类为关系被维护端
    // mappedBy="teacher"中的teacher是Student中的author属性
    @OneToMany(mappedBy = "teacher", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Student> students;

    @Column(name = "teacher_name")
    private String name;

    @ManyToMany(mappedBy = "teachers")
    private List<School> schools;
}
@Entity
@Table(name = "STUDENT")
public class Student {

    @Id
    @GenericGenerator(name = "jpa-uuid", strategy = "uuid")
    @GeneratedValue(generator = "jpa-uuid")
    @Column(name = "student_id")
    private String studentId;

    @Column(name = "student_name",length = 48)
    private String name;

    @Column(name = "student_age")
    private int age;

    @Column
    private boolean gender;

    // 要在关系的维护端,即 One 端。cascade只能写在 One 端。
    // Student ManyToOne Teacher, Teacher就是one的一端
    // optional=false,表示teacher不能为空。删除学生,不影响老师
    @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH}, optional = false) 
    private Teacher teacher;
}

2. @ManyToMany和单向@OneToMany

@Entity
@Table(name = "SCHOOL")
public class School {

    @Id
    @GenericGenerator(name = "jpa-uuid", strategy = "uuid")
    @GeneratedValue(generator = "jpa-uuid")
    @Column(name = "class_id")
    private String classId;

    @Column(name = "class_name")
    private String className;
    
    // 在Student表增加一个外键列来实现一对多的 **单向关联**, Student表中会多一列classroom_id
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "classroom_id")
    private List<Student> students;

    /*多对多关系中一般不设置级联保存、级联删除、级联更新等操作。

      可以随意指定一方为关系维护端,这里指定 SCHOOL 为关系维护端,所以生成的关联表名称为: school_teacher,关联表的字段为:classroom_id 和 teacher_id。

      多对多关系的绑定由关系维护端来完成,即由 classroom.setTeacher(teacher) 来绑定多对多的关系。关系被维护端不能绑定关系,即Teacher不能绑定关系。

      多对多关系的解除由关系维护端来完成,即由Classroom.getTeacher().remove(teacher)来解除多对多的关系。关系被维护端不能解除关系,即Teacher不能解除关系。

      如果 SCHOOL 和 Teacher 已经绑定了多对多的关系,那么不能直接删除 Teacher,需要由 SCHOOL 解除关系后,才能删除 Teacher。但是可以直接删除 SCHOOL,因为 SCHOOL 是关系维护端,删除 SCHOOL 时,会先解除 SCHOOL 和 Teacher 的关系,再删除 Teacher。
    */
    /*
     1、关系维护端,负责多对多关系的绑定和解除
     2、@JoinTable注解的name属性指定关联表的名字,joinColumns指定外键的名字,关联到关系维护端(School)
     3、inverseJoinColumns指定外键的名字,要关联的关系被维护端(Teacher)
     4、其实可以不使用@JoinTable注解,默认生成的关联表名称为主表表名+下划线+从表表名,
     即表名为SCHOOL_TEACHER
     关联到主表的外键名:即school_id
     关联到从表的外键名:即teacher_id
     主表就是关系维护端对应的表,从表就是关系被维护端对应的表*/
    @ManyToMany
    @JoinTable(name = "SCHOOL_TEACHER",joinColumns = @JoinColumn(name = "school_id"),
            inverseJoinColumns = @JoinColumn(name = "teacher_id"))
    private List<Teacher> teachers;

}