Отношения таблицы против отношений сущности
В системе реляционных баз данных может быть только три типа табличных отношений:
- один ко многим (через столбец внешнего ключа)
- один-к-одному (через общий первичный ключ)
- многие-ко-многим (через таблицу ссылок с двумя внешними ключами, ссылающимися на две отдельные родительские таблицы)
Итак, 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
методы обеспечения того , чтобы обе стороны синхронизированы. Таким образом, если мы добавляем дочернюю сущность, дочерняя сущность должна указывать на родителя, а родительская сущность должна иметь дочерний объект, содержащийся в дочерней коллекции.
Для получения дополнительной информации о наилучшем способе синхронизации всех типов двунаправленных ассоциаций сущностей ознакомьтесь с этой статьей .