SPRING-SOURCE.RU

Отображение наследования

Spring Inheritance

У нас есть супер класс BillingDetails в котором храниться пользователь, его персональный счет и дата создания. От этого класса наследуются два других класса: CreditCard и BankAccount. У каждого свои поля.

Каждый из шаблонов представленных ранее имееют свои преимущества и недостатки.

Шаблон «Таблица для конкретного класса»

Spring Inheritance

Представляет иерархию наследования классов, используя по одной таблице для каждого конкретного класса этой иерархии.

Преимущества:

Недостатки:

В данном случае иерархия классов в базе данных представляется таким образом, что для каждого конкретного класса, то есть те которые находятся на самом низу иерархии. Создается своя таблица и в эту таблицу перегоняются все собственные поля и все поля верхних классов (родителей). То есть для каждого не абстрактного класса создаем свою таблицу.

У нас есть три объекта и в базе мы получим две таблицы CREDIT_CARD, BANK_ACCOUNT. В каждой таблице будут дублироваться поля, которые мы взяли у супер класса и дальше будут собственные поля. Это самый простой способ реализации наследования.

Такой шаблон рекомендуют использовать для самой верхушки иерархии. Так как эти абстрактные классы редко когда меняются, полиморфные запросы к ним обычне не делаются, к нижним да, а к верхним обычно нет.

Пример, класс DomainObject, содержит только одно поле - id и от этого класса наследуются все Entity. Id присутствует в каждой таблице как и в супер классе. Это по сути наш шаблон. Почему он здесь использован? Полиморфные запросы мы здесь вряд ли будет делать, нам вряд ли нужно будет получать все DomainObject. Зачем? Нам нужно получить либо все категории, всех пользователей и DomainObject-ты нам вряд ли когда понадобятся. Плюс, в DomainObject других полей вставлять тоже не будем.

В JPA есть две реализации этого шаблона.

Таблица для конкретного класса с неявным полиморфизмом

Spring Inheritance

Если мы ставим аннотацию @MappedSuperclass, то все подклассы будут иметь поля суперкласса, их даже не нужно прописывать.

То есть если будет полиморфный запрос, то будут делаться запросы к подклассам.

Таблица для конкретного класса с объединениями

Spring Inheritance

Структура таблиц такая же. При полиморфных запросах Hibernate будет использовать SQL операцию UNION и только один SELECT. За один UNION мы получим полиморфный ответ объект. Но остается проблема навигации, то есть когда мы получим доступ к конкретному BillingDetails Hibernate нужно будет сделать дополнительный запрос, узнавая к какому же он классу относится и вытащить дополнительные поля. То есть, проблема с навигацией остается, проблема с изменением схемы данных при добавлении новых полей тоже остается, но зато полиморфизм немного улучшаем.

Шаблон «Таблица для иерархии классов»

Spring Inheritance

Spring Inheritance

Представляет иерархию наследования классов в виде одной таблицы, столбцы которой соответствуют всем полям классов, входящих в иерархию.

Преимущества:

Недостатки:

В предыдущем шаблоне, на каждый класс была таблица, здесь одна таблица на всю иерархию. Здесь создается одна таблица и в ней перечисляются все поля (супер класса и подклассов). То есть одна большая таблица со множеством колонок.

Применять этот шаблон лучше там, где маленькая иерархия классов (максимум 3). Когда в наших подклассах храниться очень мало полей. Максимум полей выносим в суперкласс, а в подклассах по одному. Плюс здесь в скорости.

Для этого шаблона, так как одна таблица, нужно хранить информацию о том, какие колонки к какому классу относятся.

Дополнительная колонка которая будет отвечать что и куда называется Discriminator.

Шаблон «Таблица для каждого подкласса»

Spring Inheritance

Spring Inheritance

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

Преимущества:

Недостатки:

Первый шаблон - таблица для конкретного класса (абстрактные не храняться), второй шаблон - таблица на всю иерархию, третий шаблон - таблица создается для каджого класса иерархии (даже для абстрактного).

Создается BillingDetails с полями, и по таблице для CREDIT_CARD и BANK_ACCOUNT (в них хранятся только их собственные поля). Первичные ключи этих таблиц будут ссылаться на первичный ключ BillingDetails. Связь здесь происходит по первичным ключам.

Мы сохраненяем в базу конкретные объекты (абстрактные классы ведь не хранятся). Поэтому сохраняя BankAccount создается одна запись в BillingDetails и одна запись в BankAccount. То есть мы можем по первичному ключу их соединить.