【Hibernate】一对多关联映射

来源:互联网 发布:淘宝经典文案 编辑:程序博客网 时间:2024/05/28 03:03
【回顾】
    在前面的学习,涉及到了多对一、一对一的关联映射。按照之前我的面试回答来说,这部分的内容就算结束了。但事实上,映射关系不仅仅只是三种,本篇博客要学习到的就是一对多这样一种关联映射。
【一对多】
    1. 原理:其原理和多对一关联映射一样。在多的一端加入一个外键,指向一的一端。
    2. 示例:班级与学生之间的关系。一个班级对应着多个学生,它们的关系为一对多。
    3. 实体类代码:
学生实体类(多的一端):package com.bjpowernode.hibernate;public class Student {    private int id;      private String name;    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}班级实体类(一的一端):package com.bjpowernode.hibernate;import java.util.Set;public class Classes {       private int id;    private String name;    //因为学生不止一个,所以需要采用集合。list定义是可重复的,而set定义是不可重复的。因此在这里选择set。    private Set students;    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Set getStudents() {        return students;    }    public void setStudents(Set students) {        this.students = students;    }    }
    4. 映射配置文件:
Student.hbm.xml(多的一端):<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping>    <class name="com.bjpowernode.hibernate.Student" table="t_student">        <id name="id">        <!-- 主键采用native生成策略 -->            <generator class="native"/>        </id>        <property name="name"/>    </class></hibernate-mapping> Classes.hbm.xml(一的一端):<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping>    <class name="com.bjpowernode.hibernate.Classes" table="t_classes">        <id name="id">            <generator class="native"/>        </id>        <property name="name"/>        <!-- set标签配置学生集合 -->        <set name="students">             <!-- 指明在学生集合中表示班级主键的字段名,即将班级的主键作为学生的外键加入到学生表中 -->             <key column="classesid"/>             <!-- 班级与学生的关系为一对多,利用one-to-many标签配置,并指明学生实体类的来源 -->            <one-to-many class="com.bjpowernode.hibernate.Student"/>        </set>    </class></hibernate-mapping> 
    5. 小结:
        对于一对多的关系,
            在定义实体类的时候,在一的一端实体引用多的实体,并使用set定义集合。
            在配置映射文件的时候,在一的一端使用set标签配置多的一端,而且set标签的内容需要包含key标签指明多的一端实体的外键列名,使用<one-to-many>标签指明多的那一端实体的来源。
【比较】
    * 多对一维护的关系是:多指向一的关系,有了此关系,在加载多的时候可以将一加载上来
    * 一对多维护的关系是:一指向多的关系,有了此关系,在加载一的时候可以将多加载上来
【缺陷】
    * 因为多的一端Student不知道Classes的存在(也就是Student没有维护与Classes的关系),所以在保存Student的时候关系字段classesid是为null的,如果将该关系字段设置为非空,则将无法保存数据
    * 另外因为Student不维护关系,而Classes维护关系,Classes就会发出多余的update语句,保证Classes和Student有关系,这样加载Classes的时候才可以把该Classes对应的学生加载上来
    因为存在以上缺陷,所以对于一对多的关系,一般都采用双向配置。
【一对多双向配置】
    1. 实体类代码:
一的一端已经存在对多的引用,所以只需要在多的一端加入对一的一端的引用,Student实体类:
package com.bjpowernode.hibernate;public class Student {    private int id;        private String name;        private Classes classes;    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Classes getClasses() {        return classes;    }    public void setClasses(Classes classes) {        this.classes = classes;    }}
    2. 配置映射文件:
在一的一端同样已经存在对多的配置,所以只需要在多的一端加上对一的一端的配置:
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping>    <class name="com.bjpowernode.hibernate.Student" table="t_student">        <id name="id">            <generator class="native"/>        </id>        <property name="name"/>        <!-- 增加多对一关系映射,多个学生对应一个班级 -->        <many-to-one name="classes" column="classesid"/>    </class></hibernate-mapping>
    3. inverse属性:
        * inverse属性可以用在一对多和多对多双向关联上,inverse属性默认为false,为false表示本端可以维护关系,如果inverse为true,则本端不能维护关系,会交给另一端维护关系,本端失效。
        所以一对多关联映射我们通常在多的一端维护关系,让一的一端失效,所以设置为inverse为true  
    4. 小结:
        对于一对多的双向配置,解决了单向关联的缺陷,而不是需求驱动的。
【总结】
    对于一对多关联映射,其原理和多对一关联映射是一致的,但两者也存在差别,简单地说是所站的角度不同。
    同样地,一对多关联映射也分单向和双向两种,但与其它关联映射不同的是,一对多一般都采用双向关联,不是因为需求驱动,而是因为单向存在无法插入数据或多执行重复的update语句的缺陷。
0 0