Использование mappedBy в JPA и Hibernate: объяснение

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Атрибут mappedBy в JPA и Hibernate определяет ту сторону двунаправленной ассоциации между сущностями, которая не излагает данное отношение, и ссылается на поле связанной сущности. Это позволяет сократить код и собрать данные об отношениях в одном месте.

Рассмотрим пример отношения "Один ко многим":

Java
Скопировать код
@Entity
public class Team {
    @OneToMany(mappedBy = "team")
    private Set<Player> players;
}

@Entity
public class Player {
    @ManyToOne
    private Team team;
}

mappedBy = "team" говорит о том, что связь между Player и Team осуществляется через поле team. Коллекция players в классе Team отражает структуру базы данных и точно описывает взаимосвязи объектов.

Кинга Идем в IT: пошаговый план для смены профессии

Владение связью и вспомогательные методы

В JPA и Hibernate владельцем связи признаётся та сторона, где установлен внешний ключ, и не указывается атрибут mappedBy. В контексте отношения "Многие к одному" владельцем выступает сторона Player. Аннотация @JoinColumn определяет связанный столбец базы данных.

Вспомогательные методы служат для синхронизации состояний двунаправленной связи:

Java
Скопировать код
public void addPlayer(Player player) {
    players.add(player);
    player.setTeam(this);
}

public void removePlayer(Player player) {
    players.remove(player);
    player.setTeam(null);
}

Для распространения операций на связанные сущности используются каскадные типы, например, CascadeType.ALL.

Управление двунаправленными ассоциациями

Для правильного функционирования двунаправленных ассоциаций крайне важно обеспечить согласованность данных:

  1. Чётко определите владельца связи.
  2. Обеспечивайте синхронизацию с помощью вспомогательных методов.
  3. Аккуратно настраивайте каскадирование операций с сущностями.
  4. Размещайте аннотации @JoinColumn на стороне, владеющей связью, а mappedBy — на противоположной.

Не соблюдение приведённых принципов может привести к нарушению целостности данных в Hibernate.

Визуализация

Представьте атрибут mappedBy как управление адресами в городе:

Markdown
Скопировать код
@OneToOne(mappedBy = "resident")
Public House house;

Public Resident resident;

🏠 ↔️ 🧍 Дом знает своего жителя

Markdown
Скопировать код
🏠 1️⃣ Главная улица — принадлежит [Алисе]
🏠 2️⃣ Главная улица — принадлежит [Бобу]
🏠 3️⃣ Главная улица — информация здесь не нужна, ведь жители помнят свои адреса!

mappedBy своего рода сообщает: "Не беспокойтесь, жители знают свои адреса, домам не надо их запоминать!"

Управление сложными связями

В сложных ситуациях mappedBy играет ключевую роль:

  • В случаях с @ManyToMany позвольте владеть связью только одной из сторон, в то время как другая должна использовать mappedBy.
  • Для производных сущностей mappedBy должен ссылаться на соответствующее поле суперкласса, чтобы определение связи было однозначным.
  • Если связи не подвержены изменениям, ограничьте mappedBy только чтением, чтобы не допустить случайных изменений сущностей.

Владение информацией о mappedBy — ключ к написанию чёткого и понятного кода.

Полезные материалы

  1. Java Persistence API — разработка проще с использованием модели управления сущностями — Обзор программного интерфейса JPA.
  2. OneToMany (API спецификации Java(TM) EE 7) — Официальная документация, посвящённая атрибуту mappedBy.
  3. java – Что же представляет собой "владеющая сторона" в ORM-отображении? – Stack Overflow — Обсуждение владения отношениями в ORM на StackOverflow.
  4. Советы по синхронизации двунаправленных ассоциаций с JPA и Hibernate – Влад Михальча — Рекомендации по синхронизации ассоциаций.
  5. Руководство пользователя Hibernate ORM 5.4.33.Final — Подробное руководство по использованию mappedBy.
  6. Урок на YouTube — Видео-гайд по ассоциациям в JPA и Hibernate.