JavaRush/Курсы/Модуль 4. Работа с БД/Работа с иерархиями сущностей

Работа с иерархиями сущностей

Открыта

Проблемы сохранения

Сегодня у нас будет новая и суперинтересная схема — использование возможностей Hibernate для сохранения в базу иерархии классов.

Иерархия классов — это несколько классов, связанных друг с другом отношением наследования.

Представь, что у тебя есть три класса, которые ты хочешь хранить в базе:

class User {
  int id;
  String name;
  LocalDate birthday;
}
class Employee extends User {
 	String occupation;
 	int salary;
 	LocalDate join;
}
class Client extends User {
   String address;
}

Классы унаследованы друг от друга. А самое интересное в том, что ты хочешь использовать Hibernate для того, чтобы хранить объекты этих классов в базе данных.

Виды решений

В Hibernate существует 4 возможных способа, которыми он может связать иерархию классов с таблицами в базе данных:

  • MappedSuperclass
  • Single Table
  • Joined Table
  • Table per class

Каждая стратегия предполагает свою собственную структуру таблиц в базе данных. Иногда они довольно сложные. Зато запросы на HQL к ним очень простые. Это как раз тот случай, где ярко проявляются преимущества Hibernate.

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

Ниже мы разберем, что означает каждый их них.

@MappedSuperClass

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

CREATE TABLE user {
  id INT,
  name VARCHAR,
  birthday DATE
}
CREATE TABLE employee {
  id INT,
  name VARCHAR,
  birthday DATE,
  occupation VARCHAR,
  salary INT,
  join DATE
}
CREATE TABLE client {
  id INT,
  name VARCHAR,
  birthday DATE,
  address VARCHAR
}

О том, что классы для этих таблиц связаны в иерархию, знаешь только ты. Если ты хочешь, чтобы еще и Hibernate об этом знал, тебе нужно добавить родительскому классу аннотацию @MappedSuperclass. Без нее Hibernate просто проигнорирует поля и аннотации родительского класса.

Классы с этой аннотацией будут выглядеть так:

@MappedSuperclass
class User {
  int id;
  String name;
  LocalDate birthday;
}
@Entity
class Employee extends User {
 	String occupation;
 	int salary;
 	LocalDate join;
}
@Entity
class Client extends User {
   String address;
}

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

Запросы к базе данных на HQL будут возвращать только ту сущность, тип которой указан явно. Ты не можешь написать запрос к базе на HQL и получить список всех пользователей: User, Employee, Client.

1
Задача
Модуль 4. Работа с БД,  15 уровень,  0 лекция
Недоступна
Стратегия MappedSuperClass
Стратегия MappedSuperClass
Комментарии (12)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Егор СтепановРаботает в АйЭмТи
8 апреля 2025, 09:55
В условие задачи пишется: "Для избежания дублирования используй наследование. Расставь правильно аннотации созданным классам. Не забудь про поле Long id в каждом классе-сущности." На деле же валидатор принимает только через Integer. Кстати Id указал только для класса Person.
13 мая, 11:26
Вообще дичь какая то
Олег
Уровень 109
Expert
1 августа 2024, 05:23
про Long id тоже не понял, валик принял Integer
Руслан
Уровень 115
26 июля 2024, 14:19
В задаче над классом Person дополнительно поставили аннотацию @Table, но её не надо ставить т.к. класс обозначенный @MappedSuperClass нельзя добавить в таблицу
Ольга Николенко
Уровень 115
Expert
11 июня 2024, 14:16
Не верьте условиям в задаче) нужен Integer id и не во всех классах. (валидатор требует)
Дмитрий
Уровень 117
Expert
31 января 2024, 06:08
Не получается сохранить объект класса User, класс не мапится на таблицу. Его можно сохранить вообще, или это не предусмотрено? Такое ощущение, что в примерах многое опущено.
SchlechtGut
Уровень 2
19 августа 2023, 10:14
полиморфный запрос доступен. При этом нужно указать полное название класса (вместе с пакетом)
Александр
Уровень 111
Expert
6 февраля 2023, 10:10
Прописал айдишке Long, как просят в условии, не приняло. Написал Integer и прошел валидацию. Зачем вводить в заблуждение этой фразой "Не забудь про поле Long id в каждом классе-сущности"?
Алексей
Уровень 53
2 апреля 2025, 06:36
Странно что спустя год так и не исправили :(
Алексей
Уровень 91
Expert
7 декабря 2022, 20:03
В задачке нужно не просто классы создать, но и все аннотации включая поля и геттеры с сеттерами, хотя в задании в требованиях это не указано
Nikita Shamrai Backend Developer Expert
10 декабря 2022, 11:38
Геттеры и сеттеры должны быть по стандарту в любом Энтити классе
JustinianJudge в Mega City OneMaster
9 февраля 2023, 03:15
это учебная задача, поэтому да, надо писать геттеры и сеттеры не ошибешься. Но если говорить за реальные классы, то нужно взвешивать, что требуется и почему, вот мысли на тему можно почитать https://thorben-janssen.com/access-strategies-in-jpa-and-hibernate/ Главное чтобы стандарты были для нас и решали некие проблемы, а не мы для стандартов. Хотя безусловно, по стадиям обучения, сначала мы просто повторяем, а потом разбираем зачем это и какие исключения