Ответ
Параметр fetch в аннотации @ManyToMany определяет стратегию загрузки связанных сущностей.
| FetchType | Поведение | Когда использовать |
|---|---|---|
FetchType.EAGER (по умолчанию для @ManyToMany) |
Связанная коллекция загружается немедленно вместе с владельцем, обычно одним SQL-запросом с JOIN. |
Если связанные данные почти всегда нужны сразу при загрузке основной сущности. |
FetchType.LAZY |
Коллекция загружается только при первом обращении к ней (например, вызов getRoles()). Hibernate возвращает прокси. |
Для оптимизации производительности, когда связанные данные требуются не всегда. Это предпочтительная стратегия. |
Примеры:
// EAGER загрузка (может привести к "проблеме N+1" при неправильном использовании)
@ManyToMany(fetch = FetchType.EAGER)
private Set<Role> roles;
// LAZY загрузка (рекомендуется)
@ManyToMany(fetch = FetchType.LAZY)
private Set<Role> roles;
Ключевые нюансы:
LazyInitializationException: При LAZY-загрузке обращение к коллекции вне контекста открытой сессии/транзакции выбросит это исключение. Решение: использоватьJOIN FETCHв запросе или открыть транзакцию на время чтения.- Производительность: EAGER может привести к избыточной загрузке данных и падению производительности. LAZY позволяет контролировать загрузку, но требует аккуратной работы с сессией.