5.1 說明

最後,最後一個策略是每類表。這意味著每個類將使用一個單獨的表。從某種意義上說,這是同一個 MappedSuperClass,只是更新了形式。

首先,您需要使用註釋:

@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)

帶有此註釋的類將如下所示:


@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Entity
class User {
	int id;
	String name;
	LocalDate birthday;
}

@Entity
class Employee extends User {
 	String occupation;
 	int salary;
 	LocalDate join;
}

@Entity
class Client extends User {
	String address;
}

並為每個班級單獨的表格。例如,這些:


CREATE TABLE user {
	id INT,
	name VARCHAR,
	birthday DATE
}

CREATE TABLE employee {
	id INT,
	name VARCHAR,
	birthday DATE,
	occupation VARCHAR,
	salary INT,
	join DATE
}

CREATE TABLE client {
	id INT,
	name VARCHAR,
	birthday DATE,
	address VARCHAR
}

主要區別在於傳遞 id (PRIMARY KEY) 用於所有表。您不能有具有相同 id 的不同行,不僅在同一個表中,而且在這組表中。Hibernate 會處理這個。

5.2 例子

看看這一切是如何運作的非常有趣。

您可以編寫一個簡單的 HQL 查詢來獲取所有用戶:User、Employee、Client

List<User> accounts = session.createQuery("from User").list();

但是 Hibernate 反過來會生成一個非常有趣的查詢。它會從所有表中進行選擇,然後通過 UNION ALL 將其組合成一種虛擬表,然後才會搜索和/或選擇

但是為了合併不同列的表,首先需要補充假列。比如user表需要補充列:

  • occupation VARCHAR
  • salary INT
  • join DATE
  • address VARCHAR

執行前對用戶表的SQL 查詢示例UNION ALL


SELECT   id,
         name,
         birthday,
         CAST(NULL AS VARCHAR) AS occupation,
         CAST(NULL AS INT) AS salary,
         CAST(NULL AS DATE) AS join,
         CAST(NULL AS VARCHAR) AS address,
         0 AS clazz
FROM  user

執行前對員工表的SQL 查詢示例UNION ALL


SELECT   id,
         name,
         birthday,
         occupation,
         salary,
         join,
         CAST(NULL AS VARCHAR) AS address,
         1 AS clazz
FROM  employee

執行前對客戶端表的 SQL 查詢示例UNION ALL


SELECT  id,
        name,
        birthday,
        CAST(NULL AS VARCHAR) AS occupation,
        CAST(NULL AS INT) AS salary,
        CAST(NULL AS DATE) AS join,
        address,
        2 AS clazz
FROM client

好消息是 HQL 查詢將按照您希望的方式工作。

壞消息是,如果表中有大量數據,它們可能會很慢。因為首先你需要從所有表中選擇數據,然後將它們的行與 合併UNION ALL,然後才進行過濾。