В этой статье рассмотрим стратегию наследования 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) — ее можно.
Код примера тут.