Встречается на собеседованиях • сегодня

Почему возникнет проблема N+1 при выполнении UserRepository.findById() и User.getEmails().forEach(), если getUsers() является @Transactional, а поле email - @OneToMany

Проблема N+1 возникает из-за ленивой загрузки @OneToMany коллекции emails. При вызове User.getEmails() вне транзакционного контекста (или после его закрытия) Hibernate не может подгрузить emails, что приводит к LazyInitializationException. Даже если метод getUsers() помечен @Transactional, проблема останется, если:

  1. Транзакция закрывается до обращения к коллекции
  2. Используется Open Session in View (антипаттерн)

Решение:

java
@Transactional
public User getUserWithEmails(Long id) {
    User user = userRepository.findById(id).orElseThrow();
    user.getEmails().size(); // Инициализация коллекции
    return user;
}

Или использовать JOIN FETCH в запросе:

java
@Query("SELECT u FROM User u JOIN FETCH u.emails WHERE u.id = :id")
User findByIdWithEmails(@Param("id") Long id);

Лучше избегать EAGER - это может привести к избыточным запросам.

Sophi
Софи собрала все вопросы. Тренируйся и получай
офферы быстрее!
Попробовать бесплатноArrow

Следующий вопрос

Это единственный вопрос по вашему фильтру

как отвечать на вопрос
пример собеседования
фреймворки на собеседовании
типичные вопросы junior
интервью вопросы и ответы