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