Наследование с @MappedSuperclass

Аннотация @MappedSuperclass позволяет вынести общие поля в родительский класс, но при этом не создавать для него отдельную таблицу. При такой стратегии классы-наследники преобразуются в независимые таблицы. @MappedSuperclass никак не влияет на структуру в базе — это просто способ вынести общие поля.

Ниже рассмотрим пример.

Классы

Родительский класс Customer:

@Data
@NoArgsConstructor
@MappedSuperclass
public class Customer {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private long id;
    private String name;

    public Customer(String name){
        this.name =name;
    }
}

Customer — не сущность, в него просто вынесены общие поля сущностей EmployeeCustomer и ExternalCustomer. Класс Customer можно сделать  абстрактным. Ассоциаций (@ManyToOne, @OneToMany и т.д.) с ним сделать нельзя. Этот класс можно было бы назвать AbstractEntity.

Дочерние классы EmployeeCustomer и ExternalCustomer:

@Entity
@Data
public class EmployeeCustomer extends Customer {
    private int monthsInCompany;
}

@Data
@Entity
public class ExternalCustomer extends Customer {
   private long sum;
}

Таблицы

Генерируются две независимые таблицы (внешних ключей нет, только первичные):

Генерируемые таблицы
Генерируемые таблицы
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]
}

Они включают поля родительского класса и свои.

Итоги

Сохранять можно только дочерние сущности — они пойдут в независимые таблицы и будут включать поля родительской. Отдельно Customer не сохранить, это абстракция, в которую вынесена часть полей.

Поля также можно было бы вынести вовне с помощью @Embedded, но не все (кроме @Id). Здесь же мы вынесли и @Id.

Код примера есть на GitHub.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *