Описание

Каждая из перечисленных выше стратегий и приемов имеет свои преимущества и недостатки. Общие рекомендации по выбору конкретной стратегии будут выглядеть так:

Стратегия TABLE_PER_CLASS на основе UNION

Данную стратегию лучше выбирать, если полиморфные запросы и ассоциации не требуются. Если ты редко выполняешь (или не выполняешь вообще) “select user from User user”. Если у тебя нет Entity-классов, ссылающихся на User, этот вариант будет лучшим (поскольку возможность добавления оптимизированных полиморфных запросов и ассоциаций сохранится).

Стратегия SINGLE_TABLE

Данную стратегию стоит использовать:

а) Только для простых задач. В ситуациях, когда нормализация и ограничение NOT NULL являются критическими, следует отдать предпочтение стратегии №3 (JOINED). Имеет смысл задуматься, не стоит ли в данном случае полностью отказаться от наследования и заменить его делегированием.

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

И вдобавок к этому, тебе предстоит серьезный разговор с администратором БД.

Стратегия JOINED

Данная стратегия самая эффективная по скорости и CONSTRAINTS. Она подойдет в случаях, когда требуются полиморфные запросы и ассоциации, но подклассы объявляют относительно много новых полей.

Здесь стоит оговориться: решение между JOINED и TABLE_PER_CLASS требует оценки планов выполнения запросов на реальных данных, поскольку ширина и глубина иерархии наследования могут сделать стоимость соединений (и, как следствие, производительность) неприемлемыми.

Отдельно стоит принять во внимание, что аннотации наследования невозможно применить к интерфейсам.

EXPLICIT

Еще может быть ситуация, когда у тебя есть иерархия Entity-классов с совместной стратегией хранения в базе банных. Но по каким-либо причинам ты не хочешь, чтобы некий класс иерархии возвращался, когда делается запрос по базовому классу.

Для этого есть аннотация:


@Polymorphism(type = PolymorphismType.EXPLICIT)

Если мы добавим ее к классу Client:


@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
@Polymorphism(type = PolymorphismType.EXPLICIT)
class Client extends User {
   String address;
}

То HQL-запросы будут игнорировать объекты этого класса при запросе базового класса:


 List<User> accounts = session.createQuery("from User").getResultList();

Данный запрос вернет список объектов User и Employee, но не Client.