Hibernate关系映射

       前言

        类与类直接最普通的关系就是关联关系,而且关联是有方向的。部门和员工为例 - 一个部门下有多个员工,而一个员工只属于一个部门。Emp到Dept的关联或Dept到Emp的关联,称为单向关联。如果同时包含两种关联,称为双向关联。


建立单向多对一关联关系
  • 配置单向多对一关联 使用<many-to-one>元素关联

       Dept类的所有属性和DEPT表的字段一一对应,因此Dept类映射到DEPT表中。而Emp类中,dept属性是Dept类,和EMP表的外键DEPTNO对应。但在Hibernate框架中的配置映射需要

  1. 在Emp类中创建一个关联对象:

    private Dept dept;
  2. 配置文件中配置:

    <many-to-one name="dept" column="DEPTNO" class="cn.pojo.Dept" />
  • 配置双向一对多关联

       当类与类之间建立了关联,就可以方便地从一个对象导航到另一个对象,或者通过集合导航到一组对象。

       在使用面向对象语言编写的程序中,通过关联关系从一个对象导航到另一个对象显然比通过编码到数据库中查询要更加自然,无需额外编码。并且,基于关联关系,在增删改操作中还可以对相关对象实现自动化的级联处理,同样减少了编码工作量,提高了开发效率。因此可以为Dept和Emp建立双向一对多关联。

  1. 因为是双向的关联关系,两个类中都需要进行设置相关的类型。

    //Emp类中对Dept是多对一
    private Dept dept;
    //Dept类对Emp是一对多
    private Set<Emp> emps = new HashSet<Emp>();
  2. 关联的XML中进行设置相关配置

    <many-to-one name="dept" cloumn="DEPTNO" class="cn.pojo.Dept"/>
    <set name="emps">
        <key column="DEPTNO"></key>
        <one-to-many class="cn.pojo.Emp"/>
    </set>
  • 配置双向一对一关联

    • 双向的关联关系需要配置两个类中进行搭建

      //类
       private Dept dept;
       private Emp emp;
    • XML配置文件中的搭建

       //相互关系关联
       <many-to-one name="type" column="TYPE_ID" class="com.pojo.Type"/>
      
      <one-to-one name="house" class="com.pojo.House"/>
  • 双向关联关系下的增删改操作

       基于关联关系除了可以通过对象间导航实现相关对象的自动检索外,还可以在对象的增删改操作中,对相关实现自动化的级联处理。

  1. cascade属性

    在配置好双向关联的映射配置上配置属性cascade,可选参数

    none - 当Session操纵当前对象时,忽略其他关联的对象。它是cascade属性的默认值。
    save-update - 当通过Session的save、update、saveOrUpdate方法时,级联保存所有关联的瞬时状态的对象,并且级联更新所有关联的游离状态的对象
    delete - 当通过Session的delete方法删除当前对象时,会级联删除所有关联的对象
    all - 包含save-update、delete行为

2.<set>元素的inverse属性

       inverse直译为反转。Hibernate中,inverse属性指定了关联关系中的方向。参数为true或false。默认为false。inverse=”false”的为主动方,主动方会负责维护关联关系。

  • 建立多对多关联关系
           一对多关系通常仅涉及两张表,”多”方表通过外键引用”一”方表的主键来实现一对多的关联。多对多关系除了两张”多”方的表之外,还需要一张额外的表,通过外键分别引用两张”多方表的主键来实现多对多的关联。

  • 配置双向多对多关联

       1. 对于双向多对多关联,需要把其中一端的<set>元素的inverse属性设置为”true”。使用双向多对多关联完成持久化操作。

       2. 可以将直接多对多的关联改为多个一对多关联关系通过一张”中间表”来进行关联。比如:员工表与项目表就是多对多的关系。

//表 --员工(Emp)多 对 --项目(多) --中间表(ProEmp)|改成多个一对多关系
//Emp表中
private Set<ProEmp> proEmp=new HashSet<ProEmp>();
//Project表中
private Set<ProEmp> proEmp=new HashSet<ProEmp>();
//ProEmp表中
private Emp emp;
private Dept dept;
//XML配置中Emp表
<set name="proEmp" cascade="save-update" inverse="true">
    <key column="R_EMP_ID"></key>
    <one-to-many class="com.pojo.ProEmp"/>
</set>
//XML配置中Project表
<set name="proEmp" cascade="save-update" inverse="true">
    <key column="R_PRO_ID"></key>
    <one-to-many class="com.pojo.ProEmp"/>
</set>
//XML配置中ProEmp表
<one-to-many name="emp" class="cn.pojo.Emp" column="R_EMP_ID"/>
<one-to-many name="pro" class="cn.pojo.Project" column="R_PRO_ID"/>
  • 类级别的查询策略

       类级别可选的加载策略包括立即加载和延迟加载。默认延迟加载。如果元素的lazy=true,表示延迟加载;反之false表示立即加载。

  • 一对多和多对多关联的查询策略

       在映射文件中,用元素的lazy属性来配置一对多及多对多关联关系的加载策略。

<set>元素中的lazy值:
true - 默认,延迟加载
false - 立即加载
extra  - 增强延迟加载
  • 多对一关联的查询策略

    在映射文件中,用<many-to-one>元素用来设置多对一关联关系。
    <many-to-one>元素的lazy属性值:
    proxy - 默认,延迟加载
    no-proxy - 无代理延迟加载
    false - 立即加载
  • 延迟加载

    通过关联关系可以在程序中方便地获取关联对象的数据,但如果从数据中加载Dept对象时,同时自动加载所有关联的Emp对象,而程序仅仅需要访问Dept对象,那么这些关联的Emp对象就浪费内存空间。Hibernate查询Dept对象时立即查询并加载与之关联的Emp对象,这种查询策略称为立即加载。

    立即加载的不足:

    1.会执行不必要的查询语句,影响性能。
    2.可能会加载大量不需要的对象,增加系统开销,浪费空间。