Оскільки це дуже поширене питання, я написав
цю статтю , на якій ґрунтується ця відповідь.
Односпрямована асоціація «багато хто»
Як я пояснив у цій статті , якщо ви користуєтесь @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 не гарантує, що зміни стану асоціації поширюватимуться на базу даних.
Щоб отримати докладнішу інформацію про найкращий Ват для синхронізації двосторонніх асоціацій із JPA та Hibernate, перегляньте цю статтю .
Який вибрати?
Односпрямована @OneToMany
асоціація не виконує дуже добре , тому слід уникати його.
Вам краще використовувати двонаправлену, @OneToMany
яка є більш ефективною .