Отношения таблицы против отношений сущности
В системе реляционных баз данных может быть только три типа табличных отношений:
- один ко многим (через столбец внешнего ключа)
- один-к-одному (через общий первичный ключ)
- многие-ко-многим (через таблицу ссылок с двумя внешними ключами, ссылающимися на две отдельные родительские таблицы)
Итак, one-to-manyтабличное отношение выглядит следующим образом:

Обратите внимание, что связь основана на столбце внешнего ключа (например, post_id ) в дочерней таблице.
Таким образом, существует единый источник правды, когда речь идет об управлении one-to-manyотношениями за столом.
Теперь, если вы берете двунаправленное отношение сущности, которое отображается в one-to-manyотношении таблицы, которое мы видели ранее:

Если вы посмотрите на диаграмму выше, вы увидите, что есть два способа управления этими отношениями.
В Postсущности у вас есть commentsколлекция:
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
И, в PostComment, postассоциация отображается следующим образом:
@ManyToOne(
fetch = FetchType.LAZY
)
@JoinColumn(name = "post_id")
private Post post;
Итак, у вас есть две стороны, которые могут изменить ассоциацию сущности:
- Добавляя запись в
commentsдочернюю коллекцию, новая post_commentстрока должна быть связана с родительской postсущностью через ее post_idстолбец.
- При установке
postсвойства PostCommentобъекта post_idстолбец также должен быть обновлен.
Поскольку существует два способа представления столбца «Внешний ключ», необходимо определить источник истины, когда дело доходит до перевода изменения состояния ассоциации в эквивалентную модификацию значения столбца «Внешний ключ».
MappedBy (он же обратная сторона)
mappedByАтрибут говорит о том , что @ManyToOneсторона отвечает за управление столбцом внешнего ключа, а коллекция используется только для извлечения дочерних объектов и каскадных родительской сущность изменений состояния детей (например, удаление родителя должен также удалить дочерние объекты).
Она называется обратной стороной, потому что она ссылается на свойство дочернего объекта, которое управляет этим отношением таблицы.
Синхронизировать обе стороны двунаправленной ассоциации
Теперь, даже если вы определили mappedByатрибут и дочерняя сторона @ManyToOneуправляет столбцом внешнего ключа, вам все равно нужно синхронизировать обе стороны двунаправленной ассоциации.
Лучший способ сделать это - добавить эти два служебных метода:
public void addComment(PostComment comment) {
comments.add(comment);
comment.setPost(this);
}
public void removeComment(PostComment comment) {
comments.remove(comment);
comment.setPost(null);
}
addCommentИ removeCommentметоды обеспечения того , чтобы обе стороны синхронизированы. Таким образом, если мы добавляем дочернюю сущность, дочерняя сущность должна указывать на родителя, а родительская сущность должна иметь дочерний объект, содержащийся в дочерней коллекции.
Для получения дополнительной информации о наилучшем способе синхронизации всех типов двунаправленных ассоциаций сущностей ознакомьтесь с этой статьей .