Друкарня від WE.UA

Я Java розробник і в вільний час займаюсь розробкою власного застосунку про який думаю, ще напишу окремий довгочит. В цьому ж довгочиті я хотів би поділитись проблемою пов’язаною з наслідуванням в сутностях із якою я стикнувся під час розробки.


Як виглядає наслідування в сутностях і що це таке ?

Насамперед розповім про те, як взагалі виглядає наслідування в сутностях в Hibernate. Для прикладу побудуємо класичну ієрархію з фігурами.

Схемка з сутностями фігур

Ну і звичайно приклад коду створення цієї ієрархії:

@Entity(name = "shapes")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "shape_type", 
        discriminatorType = DiscriminatorType.STRING)
public class Shape {
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Id
    private Long id;
}
@Entity
@DiscriminatorValue("rectangle")
public class Rectangle extends Shape {
    private Double length;
    private Double width;
}
@Entity
@DiscriminatorValue("circle")
public class Circle extends Shape {
    private Double radius;
}

В базі даних за цим приладом створиться табличка:

Створена табличка “shapes” в бд

Існує, ще кілька варіантів організації цих сутностей в базі даних окрім однієї таблиці (об’єднані таблиці, окрема таблиця на сутність). Детальніше можна почитати тут - ТИЦЬ.

Почнемо експериментувати

На такому простому прикладі проблем немає і якщо ми спробуємо дістати всі фігури ми будемо мати лише один запит до бази даних.

Hibernate: select s1_0.id,s1_0.shape_type,s1_0.radius,s1_0.length,s1_0.width from shapes s1_0

Якщо навіть будемо використовувати інші схеми організації таблиць все одно буде один запит до бази даних але з об’єднанням.

Hibernate: select s1_0.id,s1_0.clazz_,s1_0.radius,s1_0.length,s1_0.width from ( 
      select id, null::float as radius, null::float as length, null::float as width, 0 as clazz_ from shapes 
union all 
      select id, radius, null::float as length, null::float as width, 1 as clazz_ from circle 
union all 
      select id, null::float as radius, length, width, 2 as clazz_ from rectangle ) s1_0

Проблеми починаються пізніше, якщо ми хочемо додати зв’язки з іншими таблицями в похідні сутності. Для прикладу створимо сутність з кольором і додамо звязок із прямокутником (для зручнішого перегляду sql запитів буду використовувати збереження сутностей в одній таблиці). А тепер глянемо, які запити виконаються, якщо спробувати дістати всі фігури:

Hibernate: select s1_0.id,s1_0.shape_type,s1_0.radius,s1_0.color_id,s1_0.length,s1_0.width from shapes s1_0
Hibernate: select c1_0.id,c1_0.name from colors c1_0 where c1_0.id=?
Hibernate: select c1_0.id,c1_0.name from colors c1_0 where c1_0.id=?
Hibernate: select c1_0.id,c1_0.name from colors c1_0 where c1_0.id=?
Hibernate: select c1_0.id,c1_0.name from colors c1_0 where c1_0.id=?
Hibernate: select c1_0.id,c1_0.name from colors c1_0 where c1_0.id=?

Ми бачимо класичний приклад N + 1 проблеми. Ми маємо один загальний запит і багато окремих запитів на те, щоб дістати з бази даних кольори для кожного з прямокутників.

Вирішення N + 1 проблеми

Ті хто використовують Hibernate мабуть знають, що є кілька основних способів щоб вирішити цю проблему.

  • @Fetch(FetchMode.JOIN) анотація, детальніше тут - ТИЦЬ.

  • Entity Graphs, детальніше тут - ТИЦЬ.

Обидва з цих методів не працюють якщо в вас є ієрархія в сутностях. Єдиний спосіб, що в мене працював це прописувати join fetch в анотаціях @Query в репозиторіях, наприклад:

public interface ShapeRepo extends JpaRepository<Shape, Long> {

    @Query("select s from shapes s left join fetch s.color")
    List<Shape> findAll();
}

Такий спосіб працює і в ми маємо лише один запит до бази даних з джойном:

select s1_0.id,s1_0.shape_type,s1_0.radius,c1_0.id,c1_0.name,s1_0.length,s1_0.width from shapes s1_0 left join colors c1_0 on c1_0.id=s1_0.color_id

Нова проблема

Але все не так просто, як здається здавалось би додаємо fetch до запитів і все працює добре, але ні… Давайте створимо сутність наприклад Картинка і зробимо звязок багато до багатьох з Колом. А зв’язок між Кольором і Прямокутником також змінимо на багато до багатьох.

Але якщо ми спробуємо за попередньою схемою зробити запит:

@Query("select s from shapes s left join fetch s.colors left join fetch s.images")
List<Shape> findAll();

То отримаємо помилку:

org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags: [com.taraskovaliv.demo.entities.Circle.images, com.taraskovaliv.demo.entities.Rectangle.colors]

Рішення цієї проблеми для унаслідуваних сутностей я так і не знайшов.

Висновок

Підсумовуючи все вищескразане скажу що краще уникати наслідування в сутностях, якщо потрібно якось розділити бізнес логіку switch працює добре. Наслідування в сутностях викликає багато проблем з оптимізацією кількостів запитів до бази даних, що може привести до проблем якщо ваші дочірні сутності мають зв’язки з іншими базами даних.

P.S.

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

Статті про вітчизняний бізнес та цікавих людей:

  • Як модні бренди формують культуру та впливають на глобальні fashion-тренди

    Модні бренди часто стають символами ідентичності. Вони впливають на вибір способу життя не тільки в одязі — розкішні годинники, парфуми, товари для дому та враження підкріплюють культурні наративи успіху, смаку та вишуканості.

    Теми цього довгочиту:

    Мода
  • Створити блог на Друкарні - швидко, легко та безкоштовно

    Друкарня - це зручне та безкоштовне середовище для ведення власного блогу. В даній статті ми розповідаємо про основні переваги та функціональні можливості для того, щоб зацікавити нових авторів створити власний блог на Друкарні. Будь ласка, поширте цю інформацію.

    Теми цього довгочиту:

    Друкарня
  • Чому Google Merchant Center може заблокувати обліковий запис?

    Одним з найбільш ефективних каналів продажів є система Google Merchant Center. Правда, акаунт в ній може бути несподівано заблокований, якщо при його налаштуванні були порушені правила системи. У статті розглянемо підводні камені і дамо відповідь як уникнути блокування

    Теми цього довгочиту:

    Google Merchant Center
  • Бухгалтерський супровід ФОП: сучасний підхід до обліку

    Завдяки розвитку інформаційних технологій, впровадженню сучасних рішень і сервісів процес ведення бухобліку бізнесу став значно простішим і зручним. З іншого боку, ті ж технології додали бухгалтерам роботи – з обліком онлайн-продажів і надходжень у валюті, CRM-системами та ін.

    Теми цього довгочиту:

    Бухгалтерський Облік Фоп
  • Пилосос як базова техніка для щоденного прибирання

    Підтримання чистоти в оселі потребує зручних і продуманих рішень, особливо коли йдеться про догляд за різними поверхнями. У домашньому побуті пилосос залишається базовою побутовою технікою, що поєднує сухе та вологе очищення без зайвих зусиль.

    Теми цього довгочиту:

    Пилососи
Поділись своїми ідеями в новій публікації.
Ми чекаємо саме на твій довгочит!
Taras Kovaliv
Taras Kovaliv@taras_kovaliv we.ua/taras_kovaliv

Java розробник з ціллю

3Довгочити
289Прочитання
22Підписники
Підтримати
На Друкарні з 15 квітня

Більше від автора

Це також може зацікавити:

  • Що таке пакети в Linux, і чому в Windows не так?

    Коли людина тільки приходить в Linux, вона чує багато незрозумілих їй слів. Одним із таких слів є “Пакети“. І ні, це не ті пакети, в котрих рашиків додому відправляють… кхм. Тому давайте розберемося з пакетами в Linux, розглянемо гарні та не дуже сторони.

    Теми цього довгочиту:

    Linux
  • Український IT. Автоматичний переклад відео YouTube з англійської на українську та інші цікаві проєкти

    У цьому пості ви дізнаєтеся про проєкт для перекладу відео над яким я зараз працюю, розповім про успіхи мого попереднього проєкту, поділюся українським аналогом Buy Me A Coffee та Patreon й багато чого іншого

    Теми цього довгочиту:

    It
  • Нова спільнота web розробників

    У сучасному цифровому світі важливо мати майданчики, де фахівці можуть обмінюватися досвідом, отримувати підтримку та навчатися. Для українських веб-розробників з’явився новий ресурс — WOX (https://wox.in.ua).

    Теми цього довгочиту:

    Websites

Коментарі (4)

А навищо вам наслідування для Entities?

Це також може зацікавити:

  • Що таке пакети в Linux, і чому в Windows не так?

    Коли людина тільки приходить в Linux, вона чує багато незрозумілих їй слів. Одним із таких слів є “Пакети“. І ні, це не ті пакети, в котрих рашиків додому відправляють… кхм. Тому давайте розберемося з пакетами в Linux, розглянемо гарні та не дуже сторони.

    Теми цього довгочиту:

    Linux
  • Український IT. Автоматичний переклад відео YouTube з англійської на українську та інші цікаві проєкти

    У цьому пості ви дізнаєтеся про проєкт для перекладу відео над яким я зараз працюю, розповім про успіхи мого попереднього проєкту, поділюся українським аналогом Buy Me A Coffee та Patreon й багато чого іншого

    Теми цього довгочиту:

    It
  • Нова спільнота web розробників

    У сучасному цифровому світі важливо мати майданчики, де фахівці можуть обмінюватися досвідом, отримувати підтримку та навчатися. Для українських веб-розробників з’явився новий ресурс — WOX (https://wox.in.ua).

    Теми цього довгочиту:

    Websites