阅读 11

【JPA专题】08.映射关系_一对多双向

映射关系

C.双向一对多映射关系

关键的问题:就是设置多方维护关系

一方和多方都是用@JoinColumn,双方都有维护外键的权力,导致的结果如下

基础关系代码:多方学生类

package com.os.model;

import javax.persistence.*;

@Entity
@Table(name = "jpa_student")
public class Student {

    private Integer studentId;
    private String studentName;
    private String sex;

    private ClassInfo classInfo;

    public Student() {}

    public Student(String studentName, String sex) {
        this.studentName = studentName;
        this.sex = sex;
    }
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Integer getStudentId() {
        return studentId;
    }

    public void setStudentId(Integer studentId) {
        this.studentId = studentId;
    }
    @Column(name = "student_name")
    public String getStudentName() {
        return studentName;
    }

    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
    /*
    * 映射多对一的单向关系,@ManyToOne
    * 使用@JoinColumn指定外键字段
    * */
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "class_id")
    public ClassInfo getClassInfo() {
        return classInfo;
    }

    public void setClassInfo(ClassInfo classInfo) {
        this.classInfo = classInfo;
    }
}

复制代码

基础关系代码:一方班级类

package com.os.model;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Entity
@Table(name = "jpa_class")
public class ClassInfo {
    private Integer classId;
    private String className;

    private Set<Student> studentSet = new HashSet<>();

    public ClassInfo(){}

    public ClassInfo( String className) {
        this.className = className;
    }
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Integer getClassId() {
        return classId;
    }

    public void setClassId(Integer classId) {
        this.classId = classId;
    }
    @Column(name = "class_name")
    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }
    /*
        映射单向 一对多 的关联关系
        使用 @OneToMany 来映射 一对多 的关联关系
        使用 @JoinColumn(name = "class_id") 来映射多方的外键字段名称
     */
    @OneToMany/*(fetch = FetchType.EAGER,cascade = CascadeType.ALL)*/
    @JoinColumn(name = "class_id")
    public Set<Student> getStudentSet() {
        return studentSet;
    }

    public void setStudentSet(Set<Student> studentSet) {
        this.studentSet = studentSet;
    }
}
复制代码

注意:@JoinColumn(name = "class_id")中的字段名称应该保存一致

1.先保存一方,再保存多方,由一方维护关系

@Test
public void test01(){
    ClassInfo classInfo = new ClassInfo("起航班级");

    Student s1 = new Student("小白","男");
    Student s2 = new Student("大黄","男");
    //一方维护关系
    classInfo.getStudentSet().add(s1);
    classInfo.getStudentSet().add(s2);

    //先保存一方,在保存多方
    entityManager.persist(classInfo);
    entityManager.persist(s1);
    entityManager.persist(s2);
}
复制代码

产生的SQL语句如下,需要重新维护外键关系

Hibernate: insert into jpa_class (class_name) values (?)
Hibernate: insert into jpa_student (class_id, sex, student_name) values (?, ?, ?)
Hibernate: insert into jpa_student (class_id, sex, student_name) values (?, ?, ?)
Hibernate: update jpa_student set class_id=? where id=?
Hibernate: update jpa_student set class_id=? where id=?
复制代码

2.先保存多方,再保存一方,由一方维护关系

@Test
public void test01(){
    ClassInfo classInfo = new ClassInfo("起航班级");

    Student s1 = new Student("小白","男");
    Student s2 = new Student("大黄","男");
    //一方维护关系
    classInfo.getStudentSet().add(s1);
    classInfo.getStudentSet().add(s2);

    //先保存多方,在保存一方
    entityManager.persist(s1);
    entityManager.persist(s2);
    entityManager.persist(classInfo);
}
复制代码

产生的SQL语句如下,需要重新维护外键关系

Hibernate: insert into jpa_student (class_id, sex, student_name) values (?, ?, ?)
Hibernate: insert into jpa_student (class_id, sex, student_name) values (?, ?, ?)
Hibernate: insert into jpa_class (class_name) values (?)
Hibernate: update jpa_student set class_id=? where id=?
Hibernate: update jpa_student set class_id=? where id=?
复制代码

3.先保存多方,再保存一方,由多方维护关系

@Test
public void test01(){
    ClassInfo classInfo = new ClassInfo("起航班级");

    Student s1 = new Student("小白","男");
    Student s2 = new Student("大黄","男");
    //多方维护关系
    s1.setClassInfo(classInfo);
    s2.setClassInfo(classInfo);

    //先保存多方,在保存一方
    entityManager.persist(s1);
    entityManager.persist(s2);
    entityManager.persist(classInfo);
}
复制代码

产生的SQL语句如下,需要重新维护外键关系

Hibernate: insert into jpa_student (class_id, sex, student_name) values (?, ?, ?)
Hibernate: insert into jpa_student (class_id, sex, student_name) values (?, ?, ?)
Hibernate: insert into jpa_class (class_name) values (?)
Hibernate: update jpa_student set class_id=?, sex=?, student_name=? where id=?
Hibernate: update jpa_student set class_id=?, sex=?, student_name=? where id=?
复制代码

4.先保存一方,再保存多方,由多方维护关系

@Test
public void test01(){
    ClassInfo classInfo = new ClassInfo("起航班级");

    Student s1 = new Student("小白","男");
    Student s2 = new Student("大黄","男");
    //多方维护关系
    s1.setClassInfo(classInfo);
    s2.setClassInfo(classInfo);

    //先保存一方,在保存多方
    entityManager.persist(classInfo);
    entityManager.persist(s1);
    entityManager.persist(s2);
}
复制代码

产生的SQL语句如下

Hibernate: insert into jpa_class (class_name) values (?)
Hibernate: insert into jpa_student (class_id, sex, student_name) values (?, ?, ?)
Hibernate: insert into jpa_student (class_id, sex, student_name) values (?, ?, ?)
复制代码

个人推荐方式!!!

通过上述测试:我们发现如果使用一方维护关系会产生多于的UPDATE语句,所以我们不应该让一方维护关联的关系。

如何取消一方维护关系的权力,我们推荐使用mappedBy属性只是,该值为Student中ClassInfo中的变量名称。

@OneToMany(mappedBy = "classInfo")/*(fetch = FetchType.EAGER,cascade = CascadeType.ALL)*/
//@JoinColumn(name = "class_id")
public Set<Student> getStudentSet() {
    return studentSet;
}
复制代码
特别注意:@JoinColumn和mappedBy属性是不能共存的!
关注下面的标签,发现更多相似文章
评论