zoukankan      html  css  js  c++  java
  • Hibernate【关联映射】

     

     Hibernate可以以面向对象的方式进行数据库访问,既然是面向对象,我们知道在客观世界中,对象不会孤立的存在,在Hibernate中,Hibernate把这种对象与对象之间的联系称为关联关系,如果在我们设计实体类的时候,可以良好的映射这些关联关系,便可以大大简化持久层数据的访问

      关联关系分为两类:

        单向关系:假如学生,老师这个例子,单向关系就是指只能从老师可以访问学生,或者只能从学生访问老师

         双向关系:还是上面的例子,双向关系是指 能从老师访问学生,能从学生访问老师

     单向关系中具体的还有:                   双向关系中具体的有:

        1 -> 1               1 <-> 1

        1 -> N                1 <-> N

        N -> N              N <-> N

        N -> 1

      


    (一) 【单向】1 -> N关联

      在单向1 -> N关联中,一的持久化类中需要一个集合属性来关联到N的一方,表示有多个N。

      持久化类结构如下:

    public class Person implements Serializable{
        private Integer id; //标识符属性
        private String name; //一般属性
        private Set<Address> addresses; //关联对象
           .....
    }
    
    ---1 -> N(从一个人身上可以知道了他多个住址,而只找到住址,住址不会告诉你这是谁住的)----
    
    public class Address implements Serializable {
        private Integer id;
        private String place;
            ...
    }
    • 无连接表的关联(外键表示关联关系)

      配置关联关系的两种方式:

        方式一: 使用映射文件(重点)

          (1)*.hbm.xml中核心配置

        <!-- set元素针对的就是持久化类中的Set属性 cascade操作的是一般属性 inverse针对的是外键操作-->
        <set name="addresses" cascade="save-update"  >
                <!-- 外键字段名,告诉Hibernate,personId就是外键,用这个外键建立与Address持久化类的关联 -->
                <key column="personId"></key>
           <!-- 告诉Hibernate,Person持久化类中的set集合,放的是哪个元素 -->
                <one-to-many class="domain.Address" />
          </set>

          (2)创建了外键来维护关联关系  

        从数据库查看Address表的结构:

        

       方式二:使用注解

         略

    • 有连接表的关联(第三方表维护关联关系)

      配置关联关系的方式:

       方式一。使用*.hbm.xml(重点)

        (1)*.hbm.xml中核心配置

            <set name="addresses" cascade="save-update" table="person_address" >
                <!-- 外键表主键为这两个外键id列的组合 -->
                <key column="personId"></key>
                <!-- unique的目的为防止多对一的出现,确保是单向的一对多 -->
                <many-to-many class="domain.Address" column="adresssId" unique="true" />
            </set>

       (2)创建了第三方表的方式维护关联关系  

          在数据库查看第三方表person_address:

          

       方式二。使用注解

         略

      

      【ps: session.flush()时,进行了哪些操作】

       1。Hibernate会在一级缓存中检查所有持久化状态对象,决定发出update语句或者insert语句

       2。检查所有的持久化对象的关联对象,如果关联对象是由临时状态转换过来的,发出insert语句,如果是从脱管对象转换过来的,判断副本,再决定发不发出update语句

      1 -> N 操作

        从1的一端维护时,不需要解除关系,可以直接建立关系。

        从1的一端维护关系的时候,总会发出维护关系的update语句。该update语句就是更新外键,所以1的一方维护效率并不高


    (二) 【单向】N -> 1关联

      

      概述:常见的多对一关系,是父子关系。父类不能访问子类,而其子类们都可以访问父类。

      下面用到的例子:是人和住址的关系,不论你问小区里的那个居民,都可以得到小区所在的具体地址。但通过具体地址你却不能知道小区有哪些人

    • 无连接表的 N -> 1关联

      配置关联关系的两种方式:

       方式一:使用映射文件

    <class name="domain.Person" table="PERSON">
         <id name="id"> <column name="ID"></column> 
            <generator class="increment"></generator>
         </id>
         <property name="name">
             <column name="NAME"></column>
         </property> 
        <many-to-one name="address" column="ADDRESS_ID" class="domain.Address" cascade="save-update"></many-to-one> //外键在PERSON中
    </class>        

      方式二:使用注解

        略

    • 有连接表的N -> 1关联

      配置关联关系的两种方式:

      方式一。使用映射文件配置

          <join table="person_address">
                  <key column="pID"></key>
                  <many-to-one name="address" class="domain.Address" column="aID"></many-to-one>
              </join>

      方式二。使用注解

        略


    (三) 【双向】1 <-> N关联

    • 无连接表的关联

      配置关联关系的两种方式:

        方式一。使用*.hbm.xml(重点)

          (1.1)对于1的一端*.hbm.xml采用的配置文件

            <!-- 一对多,使用集合 -->
            <set name="addresses" cascade="save-update">
                <key column="personId"></key>
                <one-to-many class="domain.Address"/>
            </set>

         (1.2)对于N的一端*.hbm.xml采用的配置文件

         
    <many-to-one name="person" class="domain.Person" column="personId" cascade="save-update"></many-to-one>

         (2) 查看两张表的数据库中的结构

      

      

        方式二。适用注解

    • 有连接表的关联

      配置关联关系的方式:

       方式一。使用*.hbm.xml(重点)

        (1.1)对于1的一端*.hbm.xml采用的配置文件

            <set name="addresses" cascade="save-update" table="person_address">
                <key column="personId"></key>
                <many-to-many class="domain.Address" column="addressId"/>
            </set>

        (1.2)对于N的一端*.hbm.xml采用的配置文件

            <!-- join元素强制使用连接表 -->
            <join table="person_address">
                <key column="addressId"></key>
                <many-to-one name="person" class="domain.Person" column="personId" cascade="save-update"></many-to-one>
            </join>

        (2) 查看两张表的数据库中的结构

      

        方式二。使用注解

      总结:

        用1的一方维护关系,1的一方始终会发出维护关系的sql语句,

        如果用多的一方维护关系,他操作的就是N的本身。没有维护关系之说。

        所以多的一方维护效率比较高

      


    (四) 【单向】N -> N关联

      

    • 无连接表的关联

        N -> N 没有外键关联方式。

    • 有连接表的关联

      配置关联关系的方式:

      方式一:使用*.hbm.xml(重点)

            <set name="stations"  cascade="save-update" table="BUS_STATION">
                <key column="bId"></key>
                <many-to-many class="domain.Station" column="sID"></many-to-many>
            </set>

      方式二:使用注解

         略


    (五) 【双向】N -> N关联

    • 无连接表的关联

        N -> N 没有外键关联方式

    • 有连接表的关联

      配置关联关系的两种方式:

        方式一。使用*.hbm.xml(重点)

          (1)在N的两端配置

            <set name="stations"  cascade="save-update" table="BUS_STATION">
                <key column="bId"></key>
                <many-to-many class="domain.Station" column="sId"></many-to-many>
            </set>
    
    
    
    
            <set name="bus"  cascade="save-update" table="BUS_STATION">
                <key column="sId"></key>
                <many-to-many class="domain.Bus" column="bId"></many-to-many>
            </set>

        (2)查看数据库中的结构:ps:如果在<many-to-many>没有指定column的话,会在第三方表中生一个elt的列

          

      

          方式二:使用注解

           略


    (六) 【单向】1 -> 1关联

    • 无连接表的关联-主键关联

        方式一:使用映射文件配置

        例子:Station -> Bus。Station的主键与Bus的主键关联

        Bus映射文件不做任何改变,只需改变Station的映射文件

        <class name="domain.Station" table="STATION">
            <id name="id" type="java.lang.Integer">
                <column name="ID" />
                <generator class="foreign">
                    <param name="property">bus</param>  //该值就是Station持久化类中的属性值,也就是<one-to-one>中的值
                </generator>
            </id>
            <property name="name" type="java.lang.String">
                <column name="NAME" />
            </property>
           <one-to-one name="bus" class="domain.Bus" constrained="true" cascade="save-update"></one-to-one>
        </class>

        其中<one-to-one>中,constrained属性只能在<o-t-o>的映射中使用,如果constrained为true,则表明存在外键与关联表对应,并且关联表中肯定存在对应的的键于其对应,另外该选项最关键的是影响save和delete的先后顺序,例如在save的时候,如果constrained为true,则会先增加关联表,然后增加本表。delete的时候反之

        <one-to-one>的单向关联中,如果constrained为false,则会在查询的时候全部取出用left outer join的方式。如果constrained=true,hibernate即会延迟加载sql,只把主表的查出来,等有用到关联表的再发sql取。

    one-to- one的双向关联中,必须设置constrained=true,要不然会有重复数据读,如2个表user,car;在位false时sql如 下:select * from user a left outer join car b on a.id=b.id left outer join on user c on a.id=c.id where a.id=? 删除的时候最好删除从表,删除主表会先查询下主表,在联合查询下

        方式二:使用注解

          略

    • 无连接表的关联-外键关联

        方式一:使用映射文件      

         <many-to-one name="bus" class="domain.Bus" cascade="save-update" unique="true" column="bID"></many-to-one>

        方式二:使用注解

          略

    • 有连接表的关联

        方式一:使用映射文件

          <join table="bus_station">
                  <key column="sID"></key>
                  <many-to-one name="bus" class="domain.Bus" column="bID" cascade="save-update" unique="true"></many-to-one>
            </join>

        方式二:使用注解

           略


    (七)【双向】1 <-> 1

    •  主键关联

        方式一:使用映射文件

        

       bus.hbm.xml 
    <one-to-one name="station" class="domain.Station" cascade="save-update"></one-to-one> station.hbm.xml
      <one-to-one name="bus" class="domain.Bus" cascade="save-update"></one-to-one>

        方式二:适用注解

           略

    •  无连接表关联

        方式一:使用映射文件

      一开始我试了两个<many-to-one>的方式,试图在两张表都创建外键,但实际结果是建表虽然成功,但只能从一端维护,查阅网上给出的解决方案就是主键关联与外键关联结合的方式,就是如下所示 

        <many-to-one name="bus" class="domain.Bus" cascade="save-update" column="bID" unique="true"></many-to-one>
      <one-to-one name="station" class="domain.Station" property-ref="bus"></one-to-one>

        方式二:使用注解

          略

    •    有连接表关联

        看了上面的例子不难写出,故不再复述

  • 相关阅读:
    cocos2dx
    读书日记-快速排序算法
    vs重装找不到 $(WindowsSdkDir) 配置问题
    IOS应用FFMPEG库
    OpenGL ES2.0贴图
    OpenGL ES2.0光照
    IOS系统配置FFMEPG
    GPUImage库的使用
    spring08事务
    java10---点餐系统
  • 原文地址:https://www.cnblogs.com/xingdongpai/p/5123106.html
Copyright © 2011-2022 走看看