Hibernate使用xml檔案的每個類層次一張表


通過這種繼承策略,我們可以通過單表對映整個層次結構。 這裡,在表中建立一個額外的列(也稱為discriminator列)來標識該類。

讓我們先了解問題。下面給出的整個層次類對映到資料庫的一個表中圖解說明。

這個層次結構中有三個類。EmployeeRegular_EmployeeContract_Employee類的超類(父類別)。 讓我們來看看這個層次結構類的對映檔案。

<?xml version='1.0' encoding='UTF-8'?>
<!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.yiibai.Employee" table="emp121"
        discriminator-value="emp">
        <id name="id">
            <generator class="increment"></generator>
        </id>
        <discriminator column="type" type="string"></discriminator>
        <property name="name"></property>

        <subclass name="com.yiibai.Regular_Employee"
            discriminator-value="reg_emp">
            <property name="salary"></property>
            <property name="bonus"></property>
        </subclass>

        <subclass name="com.yiibai.Contract_Employee"
            discriminator-value="con_emp">
            <property name="pay_per_hour"></property>
            <property name="contract_duration"></property>
        </subclass>
    </class>

</hibernate-mapping>

在每個類層次結構一個表的情況下,hibernate框架新增了一個識別符號列,該框架指定了記錄的型別。 它主要用於區分記錄。要指定它,必須指定類的 discriminator 子元素。
類的子類subelement指定子類。 在這種情況下,Regular_EmployeeContract_EmployeeEmployee類的子類。

此層次結構的表結構如下所示:

列名 資料型別 是否為空 預設值 是否主鍵
id int(10) -
type varchar(254) - -
name varchar(254) - -
salary float - -
bonus int(10) - -
pay_per_hour float - -
contract_duration - -

每個類層次結構一個表範例

在這個例子中,我們建立了三個類,並在employee.hbm.xml檔案中提供了這些類的對映。

完整的工程目錄如下所示 -

下載程式碼的專案名稱:table-per-hierarchy-example-using-xml-file

1)建立持久類

您需要建立表示繼承的持久化類。讓我們為上面的層次結構建立三個類:

檔案: Employee.java

package com.yiibai;

public class Employee {
    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;
    }

}

檔案: Regular_Employee.java

package com.yiibai;

public class Regular_Employee extends Employee {
    private float salary;
    private int bonus;

    public float getSalary() {
        return salary;
    }

    public void setSalary(float salary) {
        this.salary = salary;
    }

    public int getBonus() {
        return bonus;
    }

    public void setBonus(int bonus) {
        this.bonus = bonus;
    }

}

檔案: Contract_Employee.java

package com.yiibai;

public class Contract_Employee extends Employee {
    private float pay_per_hour;
    private String contract_duration;

    public float getPay_per_hour() {
        return pay_per_hour;
    }

    public void setPay_per_hour(float payPerHour) {
        pay_per_hour = payPerHour;
    }

    public String getContract_duration() {
        return contract_duration;
    }

    public void setContract_duration(String contractDuration) {
        contract_duration = contractDuration;
    }

}

2)建立持久化類的對映檔案

上面我們已經了解了層次結構,下面來看看如何組態對映檔案。

檔案: employee.hbm.xml

<?xml version='1.0' encoding='UTF-8'?>
<!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.yiibai.Employee" table="emp121"
        discriminator-value="emp">
        <id name="id">
            <generator class="increment"></generator>
        </id>
        <discriminator column="type" type="string"></discriminator>
        <property name="name"></property>

        <subclass name="com.yiibai.Regular_Employee"
            discriminator-value="reg_emp">
            <property name="salary"></property>
            <property name="bonus"></property>
        </subclass>

        <subclass name="com.yiibai.Contract_Employee"
            discriminator-value="con_emp">
            <property name="pay_per_hour"></property>
            <property name="contract_duration"></property>
        </subclass>

    </class>

</hibernate-mapping>

3)在組態檔案中新增hbm檔案的對映

開啟hibernate.cfg.xml檔案,並新增如下對映資源的條目:

<mapping resource="employee.hbm.xml"/>

現在組態檔案將如下所示:

檔案:hibernate.cfg.xml

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<!-- Generated by MyEclipse Hibernate Tools.                   -->
<hibernate-configuration>

    <session-factory>
        <property name="hbm2ddl.auto">update</property>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/test</property>
        <property name="connection.username">root</property>
        <property name="connection.password">123456</property>
        <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <property name="show_sql">true</property>

         <mapping resource="employee.hbm.xml"/>
    </session-factory>

</hibernate-configuration>

hbm2ddl.auto屬性定義是用於在資料庫中建立自動表。

4)建立儲存持久物件的類

在這個類中,我們只是將Employee物件儲存到資料庫表中。

檔案:StoreData.java

package com.yiibai;

import org.hibernate.*;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.*;

public class StoreData {
    public static void main(String[] args) {
        // Session session = new
        // AnnotationConfiguration().configure().buildSessionFactory().openSession();
        final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
                .configure("hibernate.cfg.xml").build();
        // 2. 根據服務註冊類建立一個後設資料資源集,同時構建後設資料並生成應用一般唯一的的session工廠
        SessionFactory sessionFactory = new MetadataSources(registry)
                .buildMetadata().buildSessionFactory();

        /**** 上面是組態準備,下面開始我們的資料庫操作 ******/
        Session session = sessionFactory.openSession();// 從對談工廠獲取一個session
        Transaction t = session.beginTransaction();

        Employee e1 = new Employee();
        e1.setName("Yiibai");

        Regular_Employee e2 = new Regular_Employee();
        e2.setName("Max su");
        e2.setSalary(50000);
        e2.setBonus(5);

        Contract_Employee e3 = new Contract_Employee();
        e3.setName("Hippo su");
        e3.setPay_per_hour(1000);
        e3.setContract_duration("15 hours");

        session.persist(e1);
        session.persist(e2);
        session.persist(e3);

        t.commit();
        session.close();
        System.out.println("success");
    }
}

執行上面程式,並打資料庫表檢視執行結果。