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,然后才进行过滤。