1. Опис
І нарешті остання стратегія — це Table per class. Вона означає, що для кожного класу використовуватиметься окрема таблиця. В якомусь сенсі це той самий 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,
адреса VARCHAR
}
Основна відмінність — це те, що використовується наскрізний ID (PRIMARY KEY) для всіх таблиць. У тебе не можуть бути різні рядки з одним ID не лише в межах однієї таблиці, але і в межах цієї групи таблиць. Hibernate стежитиме за цим.
2. Приклади
Дуже цікаво розібрати, як це все працює.
Ти можеш написати простий HQL-запит, щоб отримати всіх користувачів: User, Employee, Client:
List<User> accounts = session.createQuery("from User").list();
А ось Hibernate, у свою чергу, згенерує дуже цікавий запит. Він зробить вибірку з усіх таблиць, потім об'єднає її через UNION ALL на кшталт віртуальної таблиці, і лише потім виконуватиме за нею пошук та/або вибірку.
Але щоб поєднати таблиці з різними колонками, спочатку їх потрібно доповнити фейковими колонками. Наприклад, таблицю user потрібно доповнити колонками:
occupation VARCHAR
salary INT
join DATE
адреса VARCHAR
Приклад SQL-запиту до таблиці user перед виконанням 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-запиту до таблиці employee перед виконанням UNION ALL
:
SELECT id,
name,
birthday,
occupation,
salary,
join,
CAST(NULL AS VARCHAR) AS address,
1 AS clazz
FROM employee
Приклад SQL-запиту до таблиці client перед виконанням 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
, і лише потім фільтрувати.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ