Hibernate的多对多关系

Posted Dream

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate的多对多关系相关的知识,希望对你有一定的参考价值。

1、表的关系:

 

       分别有三个表:课程表、学生表、分数表。课程和学生的关系是多对多的,因为一个学生对应多个课程,而一个课程被多个学生选修。如果用一对多、多对一的观点来看待课程和学生的关系显然是不对的,因为课程表和学生表中都没有外键。

因此,为了找到表之间多对多的关系,需要引入第三个表(分数表),分数表中含有课程表和学生表的主键,可以将两个本来没有关联的表通过第三个表连接起来。

2、实体关系表达:

学生:

public class Student {
    private Integer studentno;
    private String sname;
    private String sex;
    private String birthday;
    private String classno;
    private Float point;
    private String phone;
    private String email;
    private Set<Course> courses=new HashSet<Course>();
    public Integer getStudentno() {
        return studentno;
    }

    public void setStudentno(Integer studentno) {
        this.studentno = studentno;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getBirthday() {
        return birthday;
    }

    public void setBirthday(String birthday) {
        this.birthday = birthday;
    }

    public String getClassno() {
        return classno;
    }

    public void setClassno(String classno) {
        this.classno = classno;
    }

    public Float getPoint() {
        return point;
    }

    public void setPoint(Float point) {
        this.point = point;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Set<Course> getCourses() {
        return courses;
    }

    public void setCourses(Set<Course> courses) {
        this.courses = courses;
    }
    @Override
    public String toString() {
        return "Student{" +
                "studentno=" + studentno +
                ", sname=\'" + sname + \'\\\'\' +
                ", sex=\'" + sex + \'\\\'\' +
                ", birthday=\'" + birthday + \'\\\'\' +
                ", classno=\'" + classno + \'\\\'\' +
                ", point=" + point +
                ", phone=\'" + phone + \'\\\'\' +
                ", email=\'" + email + \'\\\'\' +
                ", courses=" + courses +
                \'}\';
    }
}

课程:

public class Course {
    private Integer courseid;
    private double credit;
    private String courseno;
    private String cname;
    private String type;
    private Integer period;
    private Set<Student> students=new HashSet<Student>();
    public Integer getCourseid() {
        return courseid;
    }

    public void setCourseid(Integer courseid) {
        this.courseid = courseid;
    }

    public double getCredit() {
        return credit;
    }

    public void setCredit(double credit) {
        this.credit = credit;
    }

    public String getCourseno() {
        return courseno;
    }

    public void setCourseno(String courseno) {
        this.courseno = courseno;
    }

    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Integer getPeriod() {
        return period;
    }

    public void setPeriod(Integer period) {
        this.period = period;
    }

    public Set<Student> getStudents() {
        return students;
    }

    public void setStudents(Set<Student> students) {
        this.students = students;
    }
    @Override
    public String toString() {
        return "Course{" +
                "courseid=" + courseid +
                ", credit=" + credit +
                ", courseno=\'" + courseno + \'\\\'\' +
                ", cname=\'" + cname + \'\\\'\' +
                ", type=\'" + type + \'\\\'\' +
                ", period=" + period +
                ", students=" + students +
                \'}\';
    }
}

两个实体中,分别创建了两个set集合存储对方实体对象。

3、多对多的配置:

(1)student.hbm.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="pers.zhb.domain">
    <class name="Student" table="student">
        <id name="studentno" column="studentno" >
            <generator class="native"></generator>
        </id>
        <property name="birthday" column="birthday"></property>
        <property name="classno" column="classno"></property>
        <property name="email" column="email"></property>
        <property name="phone" column="phone"></property>
        <property name="sex" column="sex"></property>
        <property name="sname" column="sname"></property>
        <property name="point" column="point"></property>
        <set name="courses" table="score" inverse="true">
            <key column="studentno"></key>
            <many-to-many class="Course" column="courseid"></many-to-many>
        </set>
    </class>
</hibernate-mapping>

前面的内容大多是对主键和普通属性的配置,主要是对于一对多关系的配置:

 <set name="courses" table="score" inverse=“true”>
            <key column="studentno"></key>
            <many-to-many class="Course" column="courseid"></many-to-many>
 </set>

name属性:对应的多的一方的集合名字。

table:联系student表和course表关系的第三个表。

column:student表的外键。

class:对应的多的一方(课程)的类名。

column:对应的多的一方的类的主键。

inverse:等于true相当于让学生一方放弃维护关系,因为双方同时维护关系会导致错误。

(2)course.hbm.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="pers.zhb.domain">
    <class name="Course" table="course">
        <id name="courseid" column="courseid" >
            <generator class="native"></generator>
        </id>
        <property name="courseno" column="courseno"></property>
        <property name="cname" column="cname"></property>
        <property name="credit" column="credit"></property>
        <property name="type" column="type"></property>
        <property name="period" column="period"></property>
        <set name="students" table="score">
            <key column="courseid"></key>
            <many-to-many class="Student" column="studentno"></many-to-many>
        </set>
    </class>
</hibernate-mapping>

(3)虽然联系student表和course表需要第三个表score,但是并不需要对score表进行配置。  

4、多对多的基本操作:

(1)学生和课程的多对多添加:

public static void testadd() {
        Session session = HibernateUtils.openSession();//获得session
        Transaction transaction = session.beginTransaction();//开启事务
        Student student=new Student();
        student.setSname("翟");
        student.setPoint(123f);
        student.setClassno(46);
        student.setSex("男");
        student.setBirthday("2019-11-11");
        student.setPhone("18739496522");
        student.setEmail("34288334@qq.com");

        Student student1=new Student();
        student1.setSname("翟hb");
        student1.setPoint(666f);
        student1.setClassno(46);
        student1.setSex("女");
        student1.setBirthday("2019-11-11");
        student1.setPhone("18739496522");
        student1.setEmail("34288334@qq.com");

        Course course=new Course();
        course.setCourseno("123");
        course.setCname("算法设计");
        course.setType("必修");
        course.setCredit(4);
        course.setPeriod(22);


        Course course1=new Course();
        course.setCourseno("456");
        course1.setCname("网络");
        course1.setCredit(2);
        course1.setPeriod(12);
        course1.setType("必修");

        student.getCourses().add(course);
        student.getCourses().add(course1);
        student1.getCourses().add(course);
        student1.getCourses().add(course1);

        session.save(student);
        session.save(student1);
        session.save(course);
        session.save(course1);

        transaction.commit();//提交事务
        session.close();//关闭资源
    }

分别创建了两个学生对象和两个课程对象,在学生类的集合中添加两个课程对象,同样,在课程类的集合中添加两个学生对象,并将他们转换为持久化状态。

运行结果:

学生:

 

 

 课程:

 

 

 分数:

 

 

 (2)为一个学生添加课程:

 public static void testadd1(){
        Session session = HibernateUtils.openSession();//获得session
        Transaction transaction = session.beginTransaction();//开启事务
        Student student=session.get(Student.class,1);//获得要添加的学生对象

        Course course=new Course();//创建课程对象
        course.setCname("算法设计");
        course.setType("必修");
        course.setCredit(4);
        course.setPeriod(22);
        course.setCourseno("123");

        student.getCourses().add(course);

        session.save(course);//转化为持久态

        transaction.commit();//提交事务
        session.close();//关闭资源
    }

  运行结果:

学生:

 

 

 课程:

 

 

 分数:

 

 

 可以看到学号为1的学生增加了课程id为1的课程。

(2)删除操作:

public static void testDel(){
        Session session = HibernateUtils.openSession();//获得session
        Transaction transaction = session.beginTransaction();//开启事务
        Student student=session.get(Student.class,1);//获得要添加的学生对象
        Course course=session.get(Course.class,1);
        Course course1=session.get(Course.class,2);

        student.getCourses().remove(course);
        student.getCourses().remove(course1);

        transaction.commit();//提交事务
        session.close();//关闭资源
    }

 5、级联操作:

(1)级联保存:

  public static void testadd1(){
        Session session = HibernateUtils.openSession();//获得session
        Transaction transaction = session.beginTransaction();//开启事务
        Student student=session.get(Student.class,1);//获得要添加的学生对象

        Course course=new Course();//创建课程对象
        course.setCname("算法设计");
        course.setType("必修");
        course.setCredit(4);
        course.setPeriod(22);
        course.setCourseno("123");

        student.getCourses().add(course);

        transaction.commit();//提交事务
        session.close();//关闭资源
    }
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="pers.zhb.domain">
    <class name="Course" table="course">
        <id name="courseid" column="courseid" >
            <generator class="native"></generator>
        </id>
        <property name="courseno" column="courseno"></property>
        <property name="cname" column="cname"></property>
        <property name="credit" column="credit"></property>
        <property name="type" column="type"></property>
        <property name="period" column="period"></property>
        <set name="students" table="score" cascade="save-update"><!--一对多关系配置-->
            <key column="courseid"></key><!--指定了集合表的外键-->
            <many-to-many class="Student" column="studentno"></many-to-many>
        </set>
    </class>
</hibernate-mapping>  

 与一对多、多对一相似,级联操作的运用可以减少代码量。

(2)级联删除:

可以使用,但是危险系数较高。

以上是关于Hibernate的多对多关系的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate的多对多关系

使用 JPA 和 Hibernate 提供程序的多对多关系不会创建主键

Hibernate学习笔记 --- 创建基于中间关联表的多对多映射关系

与Hibernate的多对多关系的循环序列化

使用 Spring Boot、Jackson 和 Hibernate 的多对多关系

(十三)Hibernate中的多表操作:单向多对多