5.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,
	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-запроса к таблице 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, и только потом фильтровать.

undefined
1
Задача
Модуль 4. Работа с БД, 15 уровень, 4 лекция
Недоступна
Стратегия Table per class
Посмотри на скрипт по созданию таблиц. Создай три энтити-класса по этим таблицам, которые описывают стратегию Table per class. Client и Employee унаследуй от Person. Расставь правильно аннотации созданным классам. Не забудь про необходимые параметры в аннотациях.