Шпаргалка по JPA: Аннотации и параметры связей
1. @JoinColumn
Зачем нужна:
Задает колонку внешнего ключа (FK) на owning side (владеющей стороне) связи, когда связь хранится не через отдельную таблицу, а через обычную колонку в текущей таблице.
Типичные сценарии:
@ManyToOne(всегда на этой стороне)- Owning side у
@OneToOne - Иногда однонаправленная (unidirectional) связь
@OneToMany
Пример:
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "user_id", nullable = false)
private User user;Основные параметры:
name— имя FK-колонки в текущей таблице.referencedColumnName— на какую колонку целевой таблицы ссылаемся (по умолчанию PK).nullable— может ли FK быть пустым (NULL).unique— уникальна ли колонка.insertable/updatable— участвует ли колонка в соответствующих SQL-запросах.foreignKey— настройка constraint (ограничения) внешнего ключа.
2. mappedBy
Зачем нужна:
Используется на inverse side (обратной стороне) двунаправленной связи. Она сообщает Hibernate: «Я не управляю связью. Настоящий мэппинг уже описан в поле X другой сущности».
mappedBy не создает колонку или таблицу.
Типичные сценарии:
@OneToMany(mappedBy = "...")@OneToOne(mappedBy = "...")@ManyToMany(mappedBy = "...")
Пример:
// В классе User
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Order> orders = new ArrayList<>();Важно:
Значение mappedBy — это имя Java-поля в связанной сущности, а не имя колонки в БД.
Если в Order поле называется private User user;, то в User пишем mappedBy = "user".
3. @JoinTable
Зачем нужна:
Описывает связь через промежуточную таблицу (join table).
Типичные сценарии:
@ManyToMany(стандартный способ)- Unidirectional
@OneToMany(иногда, чтобы избежать лишней колонки в дочерней таблице)
Пример:
@ManyToMany
@JoinTable(
name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id")
)
private Set<Course> courses = new HashSet<>();Как понимать параметры:
name— имя промежуточной таблицы.joinColumns— FK на текущую сущность (владельца).inverseJoinColumns— FK на связанную сущность (другую сторону).
4. cascade (Каскадирование)
Зачем нужна:
Определяет, как операции над родительской сущностью (Parent) распространяются на связанные сущности (Children).
Типы каскадирования (CascadeType):
PERSIST— сохранение родителя сохранит и детей.MERGE— обновление родителя обновит и детей.REMOVE— удаление родителя удалит детей.DETACH/REFRESH— отвязка или обновление состояния.ALL— все операции сразу.
Пример:
@OneToMany(mappedBy = "order", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<OrderLine> lines = new ArrayList<>();Когда использовать:
Когда «ребенок» жизненно зависит от родителя (например, Order -> OrderLine). Если это независимые сущности (например, Article -> Tag), каскадное удаление обычно не нужно.
5. orphanRemoval (Удаление сирот)
Зачем нужна:
Специфичный для Hibernate/JPA параметр. Удаляет дочернюю сущность из БД, если ссылка на неё была удалена из коллекции родителя.
Пример:
@OneToMany(mappedBy = "user", orphanRemoval = true)
private List<Order> orders;Поведение:
user.getOrders().remove(order1); // При сохранении order1 будет физически удален из базыОтличие от cascade = REMOVE:
cascade = REMOVE: Если удаляем User, удаляются все его Orders.orphanRemoval = true: Если мы просто убираем Order из списка внутри User, этот Order удаляется из базы.
Быстрая сводка (Cheat Sheet)
| Параметр | Где писать? | Суть |
|---|---|---|
@JoinColumn | Owning side | Настраивает колонку FK в таблице. |
mappedBy | Inverse side | Указывает на поле-владельца связи. |
@JoinTable | Обычно @ManyToMany | Создает третью таблицу для связи. |
cascade | Parent side | Прокидывает save/update/delete на детей. |
orphanRemoval | Parent side | Чистит базу от сущностей, которые «выпали» из коллекции. |