Использование mappedBy в JPA и Hibernate: объяснение
Быстрый ответ
Атрибут mappedBy в JPA и Hibernate определяет ту сторону двунаправленной ассоциации между сущностями, которая не излагает данное отношение, и ссылается на поле связанной сущности. Это позволяет сократить код и собрать данные об отношениях в одном месте.
Рассмотрим пример отношения "Один ко многим":
@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 отражает структуру базы данных и точно описывает взаимосвязи объектов.

Владение связью и вспомогательные методы
В JPA и Hibernate владельцем связи признаётся та сторона, где установлен внешний ключ, и не указывается атрибут mappedBy. В контексте отношения "Многие к одному" владельцем выступает сторона Player. Аннотация @JoinColumn определяет связанный столбец базы данных.
Вспомогательные методы служат для синхронизации состояний двунаправленной связи:
public void addPlayer(Player player) {
    players.add(player);
    player.setTeam(this);
}
public void removePlayer(Player player) {
    players.remove(player);
    player.setTeam(null);
}
Для распространения операций на связанные сущности используются каскадные типы, например, CascadeType.ALL.
Управление двунаправленными ассоциациями
Для правильного функционирования двунаправленных ассоциаций крайне важно обеспечить согласованность данных:
- Чётко определите владельца связи.
- Обеспечивайте синхронизацию с помощью вспомогательных методов.
- Аккуратно настраивайте каскадирование операций с сущностями.
- Размещайте аннотации @JoinColumnна стороне, владеющей связью, аmappedBy— на противоположной.
Не соблюдение приведённых принципов может привести к нарушению целостности данных в Hibernate.
Визуализация
Представьте атрибут mappedBy как управление адресами в городе:
@OneToOne(mappedBy = "resident")
Public House house;
Public Resident resident;
🏠 ↔️ 🧍 Дом знает своего жителя
🏠 1️⃣ Главная улица — принадлежит [Алисе]
🏠 2️⃣ Главная улица — принадлежит [Бобу]
🏠 3️⃣ Главная улица — информация здесь не нужна, ведь жители помнят свои адреса!
mappedBy своего рода сообщает: "Не беспокойтесь, жители знают свои адреса, домам не надо их запоминать!"
Управление сложными связями
В сложных ситуациях mappedBy играет ключевую роль:
- В случаях с @ManyToManyпозвольте владеть связью только одной из сторон, в то время как другая должна использоватьmappedBy.
- Для производных сущностей mappedByдолжен ссылаться на соответствующее поле суперкласса, чтобы определение связи было однозначным.
- Если связи не подвержены изменениям, ограничьте mappedByтолько чтением, чтобы не допустить случайных изменений сущностей.
Владение информацией о mappedBy — ключ к написанию чёткого и понятного кода.
Полезные материалы
- Java Persistence API — разработка проще с использованием модели управления сущностями — Обзор программного интерфейса JPA.
- OneToMany (API спецификации Java(TM) EE 7) — Официальная документация, посвящённая атрибуту mappedBy.
- java – Что же представляет собой "владеющая сторона" в ORM-отображении? – Stack Overflow — Обсуждение владения отношениями в ORM на StackOverflow.
- Советы по синхронизации двунаправленных ассоциаций с JPA и Hibernate – Влад Михальча — Рекомендации по синхронизации ассоциаций.
- Руководство пользователя Hibernate ORM 5.4.33.Final — Подробное руководство по использованию mappedBy.
- Урок на YouTube — Видео-гайд по ассоциациям в JPA и Hibernate.


