В этой статье рассмотрим стратегию наследования InheritanceType.TABLE_PER_CLASS. При такой стратегии классы преобразуются в независимые таблицы.
Классы
Родительский класс Customer:
@Data @NoArgsConstructor @Entity @Inheritance( strategy = InheritanceType.TABLE_PER_CLASS ) public class Customer { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private long id; private String name; public Customer(String name){ this.name =name; } }
Дочерние классы EmployeeCustomer и ExternalCustomer:
@Entity @Data public class EmployeeCustomer extends Customer { private int monthsInCompany; } @Data @Entity public class ExternalCustomer extends Customer { private long sum; }
Таблицы
Генерируются такие независимые таблицы (внешних ключей нет, только первичные):
Table "customer" { "id" bigint [pk, not null] "name" "character varying(255)" } Table "employee_customer" { "id" bigint [pk, not null] "name" "character varying(255)" "months_in_company" integer [not null] } Table "external_customer" { "id" bigint [pk, not null] "name" "character varying(255)" "sum" bigint [not null] }
Select из родительской сущности
Выборка генерирует сложный SQL.
TypedQuery<Customer> customers=em .createQuery("select c from Customer c", Customer.class);
Вышеприведенный JPQL преобразуется в SQL:
SELECT customer0_.id AS id1_0_, customer0_.name AS name2_0_, customer0_.months_in_company AS months_i1_1_, customer0_.sum AS sum1_2_, customer0_.clazz_ AS clazz_ FROM (SELECT id, name, NULL::int4 AS months_in_company, NULL::int8 AS SUM, 0 AS clazz_ FROM customer UNION ALL SELECT id, name, months_in_company, NULL::int8 AS SUM, 1 AS clazz_ FROM employee_customer UNION ALL SELECT id, name, NULL::int4 AS months_in_company, SUM, 2 AS clazz_ FROM external_customer) customer0_
Итоги
Сохранять можно все сущности (родительские и дочерние) — они пойдут в независимые таблицы.
Заметим, что при стратегии наследования InheritanceType.TABLE_PER_CLASS нельзя использовать такую стратегию генерации идентификатора:
@GeneratedValue(strategy = GenerationType.IDENTITY)
(Такая стратегия задает автоинкрементное поле). У нас использована @GeneratedValue(strategy = GenerationType.SEQUENCE) — ее можно.
Код примера тут.