天天看點

[翻譯] hibernate映射繼承關系(一):一張表對應一整棵類繼承樹

英文原址

網上這個主題的文章不在少數,這個系列的文章的部分價值在于給出了注解模式(Annotation)的例子。文章易懂,權當增強記憶,捎帶着練習下翻譯(翻譯不當之處請指出)。  

Hibernate中繼承關系的簡介:

java是一種面向對象語言,它可以實作繼承關系。然而,繼承卻是"對象模型-關系模型"不比對的最顯而易見的方面之一。面向對象系統能夠輕松的對“is a”和“has a”關系進行模組化。而關系模型隻能表達兩個實體間的"has a"關系。hibernate能夠把有關聯的表映射為對象,但你需要根據需要來選擇不同的映射政策。

Hibernate繼承關系映射政策分為三種:一張表對應一整棵類繼承樹、一個類對應一張表、每一個具體類對應一張表。

之一:一張表對應一整棵類繼承樹(子類和父類共享同一張表)

假設我們有一個 Person 類及其子類 Employee. 每個類包括如下屬性:

* class Person
        - firstname
        - lastname

* class Employee
        - joining_date
        - department_name                

在“一張表對應一整棵類繼承樹”這種模式中,繼承樹上的所有類的資料都存儲在一張表上,鑒别器字段(discriminator )是唯一的辨別每個類的關鍵字段。

下面是“一張表對應一整棵類繼承樹”模式的優點和缺點:

優點

這種模式提供了最好的性能,因為即使在深層繼承的情況下,檢索一條子類資料,也隻需要一次select操作。

缺點

對于任何一個子類的變更,比如增删改某字段,都将導緻資料庫表的變更。 

建表語句
CREATE TABLE `person` (
    `person_id` BIGINT(10) NOT NULL AUTO_INCREMENT,
    `firstname` VARCHAR(50) NULL DEFAULT NULL,
    `lastname` VARCHAR(50) NULL DEFAULT NULL,
    `joining_date` DATE NULL DEFAULT NULL,
    `department_name` VARCHAR(50) NULL DEFAULT NULL,
    `discriminator` VARCHAR(20) NOT NULL,
    PRIMARY KEY (`person_id`)
)                

PERSON表被用來同時存儲 Employee 和 Person 對象. 

Hibernate 繼承: XML 映射

下面的例子展示了如何用XML方式映射  Employee 和 Person 實體類. 

Person.java 

package net.viralpatel.hibernate;
 
public class Person {
 
    private Long personId;
    private String firstname;
    private String lastname;
 
    // Constructors and Getter/Setter methods,
}                

Employee.java

package net.viralpatel.hibernate;
 
import java.util.Date;
 
public class Employee extends Person {
 
    private Date joiningDate;
    private String departmentName;
 
    // Constructors and Getter/Setter methods,
}                

Person.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 package="net.viralpatel.hibernate">
 
    <class name="Person" table="PERSON" discriminator-value="P">
        <id name="personId" column="PERSON_ID">
            <generator class="native" />
        </id>
 
        <discriminator column="DISCRIMINATOR" type="string" />
 
        <property name="firstname" />
        <property name="lastname" column="lastname" />
 
        <subclass name="Employee" extends="Person" discriminator-value="E">
                <property name="departmentName" column="department_name" />
                <property name="joiningDate" type="date" column="joining_date" />
        </subclass>
    </class>
</hibernate-mapping>
           

注意這裡隻定義了一個 hibernate 映射檔案 Person.hbm.xml.

Person 和 Employee 類都定義在這同一個檔案中.

<discriminator> 标簽用來指定鑒别器列,包括列名和類型.

<subclass> 标簽用于映射子類 Employee. 注意我們沒有用正常的 <class>标簽來映射 Employee ,因為它位于繼承關系樹下端。

Person 類的鑒别器的值被指定為 “P” ,相應的 Employee 是“E”,這樣, 當Hibernate将要持久化person 或 employee時,相應的“P”或“E”将被置入鑒别器字段。

Hibernate 繼承: 注解映射

 下面的例子展示了如何用JPA注解方式來映射 Employee 和 Person 實體類。

 Person.java 

package net.viralpatel.hibernate;
 
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
 
@Entity
@Table(name = "PERSON")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
    name="discriminator",
    discriminatorType=DiscriminatorType.STRING
)
@DiscriminatorValue(value="P")
public class Person {
 
    @Id
    @GeneratedValue
    @Column(name = "PERSON_ID")
    private Long personId;
 
    @Column(name = "FIRSTNAME")
    private String firstname;
 
    @Column(name = "LASTNAME")
    private String lastname;
 
    // Constructors and Getter/Setter methods,
}                

Person 類是繼承樹的根類,是以我們使用了下面一些注解使其成為根類。

@Inheritance – 定義一個實體類繼承樹的繼承政策,這個注解隻能定義在繼承樹的根類上。

@DiscriminatorColumn – 用于當@Inheritance 的值被定義為 SINGLE_TABLE 或 JOINED 時,指定鑒别器列。 此注解隻能用于兩種類:一、繼承樹的根類,二、繼承樹的某子類,并且該子類定義了自己繼承政策。

如果在需要鑒别器列的時候,沒有使用@DiscriminatorColumn注解,那麼鑒别器列的名稱将預設為“DTYPE”,類型将預設為“STRING”。

@DiscriminatorValue – 用于指定給定實體類所對應的鑒别器列的具體值。 DiscriminatorValue 注解隻能用在具體的實體類中。如果使用了鑒别器列,但是沒有使用 DiscriminatorValue 注解,一個鑒别器值生成器将生效并産生一個鑒别器值來代表這個類。如果鑒别器列的類型是 STRING,  鑒别器列的值預設是該類的名稱。如果不采用預設值,那麼應該在繼承樹的每個類中都使用該注解。

 Employee.java 

package net.viralpatel.hibernate;
 
import java.util.Date;
 
import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.Table;
 
@Entity
@Table(name="PERSON")
@DiscriminatorValue("E")
public class Employee extends Person {
 
    @Column(name="joining_date")
    private Date joiningDate;
 
    @Column(name="department_name")
    private String departmentName;
 
    // Constructors and Getter/Setter methods,
}                

Employee類是Person類的子類,是以在映射時,使用@DiscriminatorValue注解來定義鑒别器的值,此例中,“E”将被置入鑒别器列。 

 MainClass

 package net.viralpatel.hibernate;

import java.util.Date;
 
import org.hibernate.Session;
import org.hibernate.SessionFactory;
 
public class Main {
 
    public static void main(String[] args) {
 
        SessionFactory sf = HibernateUtil.getSessionFactory();
        Session session = sf.openSession();
        session.beginTransaction();
 
        Person person = new Person("Steve", "Balmer");
        session.save(person);
 
        Employee employee = new Employee("James", "Gosling", "Marketing", new Date());
        session.save(employee);
 
        session.getTransaction().commit();
        session.close();
 
    }
}                

Main class 用來持久化 Person   和   Employee類的執行個體。注意兩個類都存儲在PERSON表中,鑒别器列用于區分兩個實體。

 輸出結果
Hibernate: insert into EMPLOYEE (FIRSTNAME, LASTNAME, discriminator) values (?, ?, 'P')
Hibernate: insert into EMPLOYEE (FIRSTNAME, LASTNAME, department_name, joining_date, discriminator) values (?, ?, ?, ?, 'E')                
[翻譯] hibernate映射繼承關系(一):一張表對應一整棵類繼承樹

需要例子中完整代碼的,原文連接配接中提供有下載下傳。

版權聲明:本文為CSDN部落客「weixin_33922670」的原創文章,遵循CC 4.0 BY-SA版權協定,轉載請附上原文出處連結及本聲明。

原文連結:https://blog.csdn.net/weixin_33922670/article/details/91804932