<rt id="hkid1"></rt>
    <s id="hkid1"><meter id="hkid1"></meter></s>
  1. <rp id="hkid1"><meter id="hkid1"></meter></rp>
    <source id="hkid1"></source>
  2. <ruby id="hkid1"><optgroup id="hkid1"></optgroup></ruby>

    Hibernate【映射】續篇

    小編:管理員 378閱讀 2022.09.14

    組件映射

    Java主要的類主要有兩種方式

    • 組合關系,組合關系對應的就是組件映射
    • 繼承關系,繼承關系對應的就是繼承映射

    組件映射實際上就是將組合關系的數據映射成一張表,組件類和被包含的組件類映射成一張表

    有的時候,兩個類的關系明顯不是繼承關系,但兩個類的親密程度很高,在一個類里邊需要用到另外一個類…那么就在類中定義一個變量來維護另一個類的關系,這種就叫組合關系!

    需求:汽車和輪子。汽車需要用到輪子,但是輪子的爸爸不可能是汽車吧?

    設計數據庫

    這里寫圖片描述

    設計實體

    Wheel.java

    public class Wheel {
    
    
    
    private int  count;
    
    private int size;
    
    
    
    public int getCount() {
    
    return count;
    
    }
    
    
    
    public void setCount(int count) {
    
    this.count = count;
    
    }
    
    
    
    public int getSize() {
    
    return size;
    
    }
    
    
    
    public void setSize(int size) {
    
    this.size = size;
    
    }
    
    }
    復制

    Car.java,使用變量維護Wheel

    package zhongfucheng.aa;
    
    
    
    /**
    
    * Created by ozc on 2017/5/7.
    
    */
    
    public class Car {
    
    
    
    private int id;
    
    private String name;
    
    private Wheel wheel;
    
    
    
    public Wheel getWheel() {
    
    return wheel;
    
    }
    
    
    
    public void setWheel(Wheel wheel) {
    
    this.wheel = wheel;
    
    }
    
    
    
    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;
    
    }
    
    }
    復制映射表

    使用了一個新標簽<component>,組件映射標簽。

    <?xml version="1.0"?>
    
    <!DOCTYPE hibernate-mapping PUBLIC
    
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
    
    
    <hibernate-mapping package="zhongfucheng.aa" >
    
    
    
    <class name="Car" table="Car" >
    
    
    
    <!--映射主鍵-->
    
    <id name="id" column="id">
    
    <generator class="native"></generator>
    
    </id>
    
    
    
    <!--映射普通字段-->
    
    <property name="name" column="name" ></property>
    
    
    
    
    
    <!--
    
    映射組件字段
    
    -->
    
    <component name="wheel">
    
    <property name="count"></property>
    
    <property name="size"></property>
    
    </component>
    
    
    
    </class>
    
    
    
    </hibernate-mapping>
    復制測試
    package zhongfucheng.aa;
    
    
    
    import org.hibernate.SessionFactory;
    
    import org.hibernate.Transaction;
    
    import org.hibernate.cfg.Configuration;
    
    import org.hibernate.classic.Session;
    
    
    
    /**
    
    * Created by ozc on 2017/5/6.
    
    */
    
    public class App5 {
    
    public static void main(String[] args) {
    
    
    
    
    
    //創建對象
    
    Wheel wheel = new Wheel();
    
    Car car = new Car();
    
    
    
    //設置屬性
    
    wheel.setCount(43);
    
    wheel.setSize(22);
    
    car.setName("寶馬");
    
    
    
    //維護關系
    
    car.setWheel(wheel);
    
    //獲取加載配置管理類
    
    Configuration configuration = new Configuration();
    
    
    
    
    
    configuration.configure().addClass(Car.class);
    
    
    
    //創建Session工廠對象
    
    SessionFactory factory = configuration.buildSessionFactory();
    
    
    
    //得到Session對象
    
    Session session = factory.openSession();
    
    
    
    //使用Hibernate操作數據庫,都要開啟事務,得到事務對象
    
    Transaction transaction = session.getTransaction();
    
    
    
    //開啟事務
    
    transaction.begin();
    
    
    
    session.save(car);
    
    
    
    //提交事務
    
    transaction.commit();
    
    
    
    //關閉Session
    
    session.close();
    
    
    
    
    
    }
    
    }
    復制

    這里寫圖片描述

    傳統方式繼承

    需求:動物、貓、猴子。貓繼承著動物

    傳統方式繼承的特點就是:有多少個子類就寫多少個配置文件.

    表結構

    我們的表應該是這樣的:id和name從Animal中繼承,catchMouse是子類的具體行為。

    這里寫圖片描述

    實體

    Animal.java

    package zhongfucheng.aa;
    
    
    
    // 動物類
    
    public abstract class Animal {
    
    
    
    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;
    
    }
    
    }
    復制

    Cat.java繼承著Animail

    package zhongfucheng.aa;
    
    
    
    public class Cat extends Animal{
    
    
    
    // 抓老鼠
    
    private String catchMouse;
    
    
    
    public String getCatchMouse() {
    
    return catchMouse;
    
    }
    
    
    
    public void setCatchMouse(String catchMouse) {
    
    this.catchMouse = catchMouse;
    
    }
    
    }
    復制
    映射文件

    簡單繼承的映射文件很好寫,在屬性上,直接寫父類的屬性就可以了。

    但是也有致命的缺點:如果子類有很多,就需要寫很多的配置文件

    <?xml version="1.0"?>
    
    <!DOCTYPE hibernate-mapping PUBLIC
    
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
    
    
    <hibernate-mapping package="zhongfucheng.aa" >
    
    
    
    <class name="Cat" table="cat" >
    
    
    
    <!--映射主鍵-->
    
    <id name="id" column="id">
    
    <generator class="native"></generator>
    
    </id>
    
    
    
    <!--
    
    映射普通字段
    
    父類的屬性直接引用就行了,比如name屬性,直接寫就行了!
    
    -->
    
    <property name="name" column="name" ></property>
    
    <property name="catchMouse" column="catchMouse" ></property>
    
    
    
    
    
    </class>
    
    
    
    </hibernate-mapping>
    復制測試
    package zhongfucheng.aa;
    
    
    
    import org.hibernate.SessionFactory;
    
    import org.hibernate.Transaction;
    
    import org.hibernate.cfg.Configuration;
    
    import org.hibernate.classic.Session;
    
    
    
    public class App5 {
    
    public static void main(String[] args) {
    
    
    
    
    
    //創建對象
    
    Cat cat = new Cat();
    
    
    
    //設置屬性
    
    
    
    cat.setName("大花貓");
    
    cat.setCatchMouse("捉大老鼠");
    
    
    
    //獲取加載配置管理類
    
    Configuration configuration = new Configuration();
    
    
    
    
    
    configuration.configure().addClass(Cat.class);
    
    
    
    //創建Session工廠對象
    
    SessionFactory factory = configuration.buildSessionFactory();
    
    
    
    //得到Session對象
    
    Session session = factory.openSession();
    
    
    
    //使用Hibernate操作數據庫,都要開啟事務,得到事務對象
    
    Transaction transaction = session.getTransaction();
    
    
    
    //開啟事務
    
    transaction.begin();
    
    
    
    session.save(cat);
    
    //如果取數據時候Animal父類接收的話,需要給出Anmail的全名
    
    
    
    
    
    //提交事務
    
    transaction.commit();
    
    
    
    //關閉Session
    
    session.close();
    
    
    
    
    
    }
    
    }
    復制

    這里寫圖片描述


    把所有子類映射成一張表

    前面我們采用的是:每個子類都需要寫成一個配置文件,映射成一張表

    如果子類的結構很簡單,只比父類多幾個屬性。就像上面的例子…我們可以將所有的子類都映射成一張表中

    但是呢,這樣是不符合數據庫設計規范的…..因為表中的數據可能是貓,可能是猴子…這明顯是不合適的…

    由于表中可能存在貓,存在猴子,為了區分是什么類型的。我們需要使用鑒別器

    我們了解一下…

    數據表

    這里寫圖片描述

    實體

    實體和上面雷同,只多了一個猴子的實體表

    Monkey.java

    public class Monkey extends Animal {
    
    // 吃香蕉
    
    private String eatBanana;
    
    
    
    public String getEatBanana() {
    
    return eatBanana;
    
    }
    
    
    
    public void setEatBanana(String eatBanana) {
    
    this.eatBanana = eatBanana;
    
    }
    
    }
    復制映射文件

    使用了subClass這個節點和鑒別器

    <?xml version="1.0"?>
    
    <!DOCTYPE hibernate-mapping PUBLIC
    
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
    
    
    <!--
    
    繼承映射, 所有的子類都映射到一張表
    
    -->
    
    <hibernate-mapping package="cn.itcast.e_extends2">
    
    <class name="Animal" table="t_animal">
    
    <id name="id">
    
    <generator class="native"></generator>
    
    </id>
    
    <!-- 指定鑒別器字段(區分不同的子類) -->
    
    <discriminator column="type_"></discriminator>
    
    <property name="name"></property>
    
    <!--
    
    子類:貓
    
    每個子類都用subclass節點映射
    
    注意:一定要指定鑒別器字段,否則報錯!
    
    鑒別器字段:作用是在數據庫中區別每一個子類的信息, 就是一個列
    
    discriminator-value="cat_"
    
    指定鑒別器字段,即type_字段的值
    
    如果不指定,默認為當前子類的全名
    
    -->
    
    <subclass name="Cat" discriminator-value="cat_">
    
    <property name="catchMouse"></property>
    
    </subclass>
    
    <!--
    
    子類:猴子
    
    -->
    
    <subclass name="Monkey" discriminator-value="monkey_">
    
         <property name="eatBanana"></property>
    
    </subclass>
    
    </class>
    
    
    
    </hibernate-mapping>
    復制測試

    加載的是Animal父類的映射文件。保存的是cat和monkey。

    package zhongfucheng.aa;
    
    
    
    import org.hibernate.SessionFactory;
    
    import org.hibernate.Transaction;
    
    import org.hibernate.cfg.Configuration;
    
    import org.hibernate.classic.Session;
    
    
    
    public class App5 {
    
    public static void main(String[] args) {
    
    
    
    
    
    //創建對象
    
    Cat cat = new Cat();
    
    Monkey monkey = new Monkey();
    
    
    
    //設置屬性
    
    cat.setName("大花貓");
    
    cat.setCatchMouse("小老鼠");
    
    monkey.setEatBanana("吃香蕉");
    
    monkey.setName("大猴子");
    
    
    
    //獲取加載配置管理類
    
    Configuration configuration = new Configuration();
    
    
    
    //加載Animal的映射文件!
    
    configuration.configure().addClass(Animal.class);
    
    
    
    //創建Session工廠對象
    
    SessionFactory factory = configuration.buildSessionFactory();
    
    
    
    //得到Session對象
    
    Session session = factory.openSession();
    
    
    
    //使用Hibernate操作數據庫,都要開啟事務,得到事務對象
    
    Transaction transaction = session.getTransaction();
    
    
    
    //開啟事務
    
    transaction.begin();
    
    
    
    session.save(cat);
    
    session.save(monkey);
    
    
    
    //提交事務
    
    transaction.commit();
    
    
    
    //關閉Session
    
    session.close();
    
    
    
    
    
    }
    
    }
    復制

    這里寫圖片描述


    每個類映射一張表(3張表)

    父類和子類都各對應一張表。那么就有三張表了

    這種結構看起來是完全面向對象,但是表之間的結構會很復雜,插入一條子類的信息,需要兩條SQL

    數據表設計

    這里寫圖片描述

    映射文件

    使用到了<joined-subclass >這個節點

    <?xml version="1.0"?>
    
    <!DOCTYPE hibernate-mapping PUBLIC
    
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
    
    
    
    
    <hibernate-mapping package="zhongfucheng.aa">
    
    
    
    <class name="Animal" table="t_animal">
    
    <id name="id">
    
    <generator class="native"></generator>
    
    </id>
    
    
    
    <property name="name"></property>
    
    
    
    
    
    <!--
    
    Animal下的子類映射成一張表
    
    指定子類的類型,對應的表
    
    指定子類的外鍵字段【需要對應Animal】
    
    指定子類的普通屬性
    
    -->
    
    <joined-subclass name="Cat" table="cat_">
    
    <!--key對應的是外鍵字段-->
    
    <key column="animal_id"></key>
    
    <property name="catchMouse"></property>
    
    </joined-subclass>
    
    
    
    <joined-subclass name="Monkey" table="monkey_">
    
    <!--key對應的是外鍵字段-->
    
    <key column="animal_id"></key>
    
    <property name="eatBanana"></property>
    
    </joined-subclass>
    
    
    
    
    
    </class>
    
    
    
    
    
    </hibernate-mapping>
    復制測試
    package zhongfucheng.aa;
    
    
    
    import org.hibernate.SessionFactory;
    
    import org.hibernate.Transaction;
    
    import org.hibernate.cfg.Configuration;
    
    import org.hibernate.classic.Session;
    
    
    
    public class App5 {
    
    public static void main(String[] args) {
    
    
    
    
    
    //創建對象
    
    Cat cat = new Cat();
    
    Monkey monkey = new Monkey();
    
    
    
    //設置屬性
    
    cat.setName("大花貓");
    
    cat.setCatchMouse("小老鼠");
    
    monkey.setEatBanana("吃香蕉");
    
    monkey.setName("大猴子");
    
    
    
    //獲取加載配置管理類
    
    Configuration configuration = new Configuration();
    
    
    
    //加載類對應的映射文件!
    
    configuration.configure().addClass(Animal.class);
    
    
    
    //創建Session工廠對象
    
    SessionFactory factory = configuration.buildSessionFactory();
    
    
    
    //得到Session對象
    
    Session session = factory.openSession();
    
    
    
    //使用Hibernate操作數據庫,都要開啟事務,得到事務對象
    
    Transaction transaction = session.getTransaction();
    
    
    
    //開啟事務
    
    transaction.begin();
    
    
    
    session.save(cat);
    
    session.save(monkey);
    
    
    
    //提交事務
    
    transaction.commit();
    
    
    
    //關閉Session
    
    session.close();
    
    
    
    
    
    }
    
    }
    復制

    每保存一個子類對象需要兩條SQL語句!

    這里寫圖片描述


    (推薦)每個子類映射一張表, 父類不對應表(2張表)
    • 使用過了一張表保存所有子類的數據,這不符合數據庫設計規范
    • 每個子類、父類都擁有一張表..表結構太過于繁瑣..添加信息時,過多的SQL

    我們即將使用的是:每個子類映射成一張表,父類不對應表…這和我們傳統方式繼承是一樣的。只不過在hbm.xml文件中使用了<union-subclass>這個節點,由于有了這個節點,我們就不需要每個子類都寫一個配置文件了。

    數據庫表設計

    這里寫圖片描述

    映射文件
    • 想要父類不映射成數據庫表,只要在class中配置為abstract即可
    • 使用了union-subclass節點,主鍵就不能采用自動增長策略了。我們改成UUID即可。當然啦,對應的實體id類型要改成String
    <?xml version="1.0"?>
    
    <!DOCTYPE hibernate-mapping PUBLIC
    
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
    
    
    
    
    <hibernate-mapping package="zhongfucheng.aa">
    
    
    
    
    
    <!--
    
    想要父類不映射成表,設置成abstract
    
    -->
    
    <class name="Animal" abstract="true">
    
    
    
    <!--
    
    如果使用了union-subclass節點,那么主鍵生成策略不能是自增長,我們改成uuid即可
    
    -->
    
    <id name="id">
    
    <generator class="uuid"></generator>
    
    </id>
    
    
    
    <property name="name"></property>
    
    
    
    
    
    <!--
    
    將子類的信息都映射成一張表
    
    給出屬性的名稱
    
    屬性對應的數據庫表
    
    普通字段
    
    -->
    
    <union-subclass name="Cat" table="cat_">
    
    <property name="catchMouse"></property>
    
    </union-subclass>
    
    
    
    <union-subclass name="Monkey" table="monkey_">
    
    <property name="eatBanana"></property>
    
    </union-subclass>
    
    
    
    
    
    </class>
    
    
    
    
    
    </hibernate-mapping>
    復制測試
    package zhongfucheng.aa;
    
    
    
    import org.hibernate.SessionFactory;
    
    import org.hibernate.Transaction;
    
    import org.hibernate.cfg.Configuration;
    
    import org.hibernate.classic.Session;
    
    
    
    public class App5 {
    
    public static void main(String[] args) {
    
    
    
    
    
    //創建對象
    
    Cat cat = new Cat();
    
    Monkey monkey = new Monkey();
    
    
    
    //設置屬性
    
    cat.setName("大花貓");
    
    cat.setCatchMouse("小老鼠");
    
    monkey.setEatBanana("吃香蕉");
    
    monkey.setName("大猴子");
    
    
    
    //獲取加載配置管理類
    
    Configuration configuration = new Configuration();
    
    
    
    //加載類對應的映射文件!
    
    configuration.configure().addClass(Animal.class);
    
    
    
    //創建Session工廠對象
    
    SessionFactory factory = configuration.buildSessionFactory();
    
    
    
    //得到Session對象
    
    Session session = factory.openSession();
    
    
    
    //使用Hibernate操作數據庫,都要開啟事務,得到事務對象
    
    Transaction transaction = session.getTransaction();
    
    
    
    //開啟事務
    
    transaction.begin();
    
    
    
    session.save(cat);
    
    session.save(monkey);
    
    
    
    //提交事務
    
    transaction.commit();
    
    
    
    //關閉Session
    
    session.close();
    
    
    
    
    
    }
    
    }
    復制

    這里寫圖片描述

    組件映射和繼承映射總結

    由于我們的傳統繼承映射每個子類都對應一個配置文件,這樣十分麻煩。因此.hbm.xml就給出了幾個節點供我們使用,分別有以下的情況:

    • 子類父類共有一張表subclass
    • 不符合數據庫設計規范
    • 需要使用鑒別器
    • 子類、父類都有自己的表joined-subclass,那么就是三張表
    • 表的結構太過繁瑣
    • 插入數據時要生成SQL至少就要兩條
    • 子類擁有自己的表、父類不對應表【推薦】union-subclass
    • 父類不對應表要使用abstract來修飾
    • 主鍵的id不能使用自增長策略,修改成UUID就好了。對應的JavaBean的id設置成String就好

    關聯標簽:
    快三群