【Hibernate】【映射文件】【關係映射】

關係映射:即需要映射的屬性,是一個實例對象.如員工的部門屬性.

單向多對一(常用)

  • MySQL的表格
    這裏寫圖片描述

  • 員工類中的屬性

    private Department dept;//dept_id
  • 屬性的映射
    • 由員工管理,在員工的映射文件設置
<many-to-one name="dept" column="dept_id"/>

案例1

有一個員工A屬於部門B,兩者都沒有存入數據庫
情況1:session.save(員工);

  • 結果:報錯
  • 原因:保存了員工後,沒有找到外鍵對應的部門

情況2:session.save(先部門,再員工)

  • 結果:正常發送兩個insert的SQL

情況3:session.save(先員工,再部門)

  • 結果:1.保存員工;2.保存部門,3.更新員工
  • 原因:保存員工爲持久化後,但其dept屬性爲臨時狀態,不受保存.保存部門後,dept又變成了持久化狀態,導致員工狀態變成髒的持久化狀態,需要更新.

案例2

        Employee e = (Employee)session.get(Employee.class, 1L);
        Department dept = e.getDept();
        System.out.println("_____________");
        System.out.println(e);  //使用了dept屬性

結果:

  1. 查員工的SQL
  2. 橫線
  3. 查部門
  4. 輸出員工

原因:e.getDept(); 取外鍵的對象,返回的是代理對象(延遲加載);使用前纔會實例化.

外鍵的代理對比load()的代理

  • load();返回的代理對象絕對不爲null,不可以用代理對象==null來判斷
  • 外鍵的代理:返回的代理對象,可能爲空,因爲查詢e時候,如果dept_id爲null,就返回null,非null,就返回代理對象.代理對象==null可以用來判斷

單向多對多(常用)

  • MySQL的表格(必有中間表)
    這裏寫圖片描述

  • Teacher類中的屬性

    • 由teacher管理student
private  Set<Student> stus;//Teacher_Student  Teacher_id/Student_id
  • 屬性的映射
        <set name="stus" table="Teacher_Student" order-by="Student_id">
            <key column="Teacher_id"/>
            <many-to-many class="Student" column="Student_id"/>
        </set>
        <set name="屬性名" table="中間表名">
            <key column="對應己方的外鍵列"/>
            <many-to-many class="他方的類" column="對應他方的外鍵列"/>
        </set>
<!--set換成bag也會按id排序,bag對應的是list-->
        <set name="stus" table="Teacher_Student" >
            <key column="Teacher_id"/>
            <many-to-many class="Student" column="Student_id"/>
        </set>

//擴展按添加順序排列
1.在Student類中添加記錄添加順序的屬性並且聲明
    private Integer sequence;
2.在Teacher映射文件中的order-by="sequence"

單向一對多(常用)

外鍵依然標記在員工表的dept_id,只不過要將部門類中添加一個屬性:

private Set<Employee> emps;//dept_id

屬性的映射

         <set name="emps">
            <key column="dept_id"/>
            <one-to-many class="Employee"/>
         </set>

案例1

員工A所屬部門B,兩者都存入db
情況1.session.save(先部門,後員工)

  • 結果:三條SQL;保存部門,保存員工,更新員工;

情況2.session.save(先員工,後部門)

  • 結果:三條SQL;保存員工,保存部門,更新員工;

情況3.session.save(部門) //單獨保存部門(部門中有爲保存的員工)會失敗

  • 結果:2條SQL;保存部門,更新員工因找不到而報錯;

案例2

        Department dept=(Department)session.get(Department.class,1L);
        Set<Employee> emps = dept.getEmps();//返回代理對象
        System.out.println("__________");
        System.out.println(dept);//調用
  • 結果:

    1. 查部門的sql
    2. 橫線
    3. 查 員工的sql
    4. 輸出部門
      原因:dept.getEmps();返回的是代理對象(延遲加載);使用前纔會實例化.該代理對象也是決不爲空,於load()一樣.要用.size()方法來判斷是否爲空.

級聯

可以通過one方來控制many方,<set cascade="XXX">
這裏寫圖片描述

  • save-update:

    • session.save(主對象):同時保存其集合中的從對象
    • session.update(主對象):1.去持久化新增的從對象;2.修改遊離的從對象;3.將已經丟出集合的從對象,其對應的外鍵設爲null;
  • delete: 刪除主對象,同時刪除其集合中的從對象(在表中刪除)

  • all:save-update+delete
  • delete-orphan:1.將外鍵設爲null的從對象,從表中刪除.2.將從集合中剔除的從對象,從表中刪除.3刪除主對象,也雙光從對象.
  • all-delete-orphan:上面的全部.訂單就要用這個.

雙向=一對多+多對一(常用)

數據庫的表格不用,一樣是員工表格有外鍵dept_id

更改映射文件

    <!--員工-->
    <class name="Employee">
         <many-to-one name="dept" column="dept_id"/>
    </class>

     <!--部門-->
     <class name="Department" inverse="true">
         <set name="emps">
            <key column="dept_id"/>
            <one-to-many class="Employee"/>
         </set>
    </class>

inverse=”true”: 表示部門放棄對關係的管理,一切由員工的映射管理.

true:刪除部門,同時會刪對應的員工;而且會出現多餘的SQL來維護二者關係
false:刪除部門,只會將員工的外鍵爲null

一對一(不常用)

QQ號對應QQ空間,可以使用QQ號的主鍵,作爲外鍵指向QQ空間的主鍵;
即QQ空間的主鍵生成,是跟隨QQ號的主鍵

<!--QQ號-->
        <one-to-one name="zone">
<!--QQ空間-->
    <!--聲明主鍵生成方式依賴別的表的主鍵-->
    <id name="id">
        <generator class="foregn">
            <param name="property">類中的QQ號屬性名</param>
        </generator >
    </id>
    <!--constained="true",表示被控制的-->
    <one-to-one name="類中的QQ號屬性名" constained="true">

組件關係

多個類,對應一個表,類與類是組件關係
類中的實例對象屬性,就是多類中的其他屬性進行一次包裝,組件對象沒有對應的表格

public class 公司{
    private Long id;
    private String name;
    private Address 營業地址;  //組件1
    private Address 註冊;      //組件2
}


public class Address {
    private String 省;
    private String 城;
    private String 街;
}

公司類的映射文件

<class name="公司">
    <id></id>
    <property></property>
<!--組件-->
    <component name="營業地址">
        <property name="省" column="表中的列1">
        ` 
        `
    </component>
<!--組件-->
        <component name="註冊地址">
        <property name="省" column="表中的列2">
        ` 
        `
    </component>
</class>

繼承關係

多個類,對應一個表,類與類是繼承關係
這裏寫圖片描述

映射文件(映射的類用父類!)

<class name="商品" discriminator-value="1">
     <id> </id>
     <property name="XX">
<!--聲明表中區別的列名-->
     <discriminator column="type" type="int">
<!--添加子類-->
    <subclass name="書" discriminator-value="2"> 
        <property name="作者"/>
    </subclass >     
        <subclass name="衣" discriminator-value="3"> 
        <property name="顏色"/>
    </subclass >     
</class>

此時 session.get(衣服.class,1L);
sql爲 wher id=1 and type = 3;

發佈了73 篇原創文章 · 獲贊 12 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章