Sobes.tech
Назад к вопросам
Junior — Middle
51

Чему может привести использование аннотации @Lazy без соответствующей аннотации @Transactional в Spring?

Ответ от нейросети

sobes.tech AI

Что хотят услышать интервьюеры:

@Lazy сам по себе откладывает создание бина до первого обращения, но не управляет транзакцией. Если после ленивой инициализации код обращается к JPA-объектам вне активной транзакции, можно получить ошибки lazy loading и LazyInitializationException. Интервьюер обычно хочет услышать, что @Lazy не заменяет @Transactional, а лишь меняет момент создания объекта.

Определение:

@Lazy в Spring говорит контейнеру не создавать бин сразу при старте приложения, а инициализировать его только при первом использовании.
@Transactional нужен для открытия и управления транзакцией на время выполнения метода.
Если объект или его зависимости загружаются лениво, но код выполняется без транзакции, доступ к данным из ORM может происходить уже после закрытия сессии/EntityManager, что приводит к ошибкам при обращении к неинициализированным связям.

Пример использования:

Например, сервис получает заказ и обращается к ленивой коллекции позиций:

@Service
public class OrderService {

    @Lazy
    @Autowired
    private OrderRepository orderRepository;

    public OrderDto getOrder(Long id) {
        Order order = orderRepository.findById(id).orElseThrow();
        return new OrderDto(order.getId(), order.getItems().size());
    }
}

Если order.getItems() — lazy association, а метод выполняется без @Transactional, доступ к коллекции может завершиться ошибкой.

Пояснение кода:

  1. @Lazy на зависимом компоненте откладывает его создание до первого использования.
  2. findById(id) возвращает сущность, у которой связь items может быть не загружена сразу.
  3. Метод getItems().size() пытается инициализировать ленивую коллекцию.
  4. Если к этому моменту транзакция уже закрыта или не была открыта, Hibernate не может добрать данные из БД.
  5. В итоге приложение получает LazyInitializationException или похожую проблему доступа к данным вне сессии.

Ключевые моменты:

  • @Lazy влияет на время создания бина, а не на границы транзакции.
  • Без @Transactional ленивые ORM-связи часто не успевают загрузиться корректно.
  • Типичный симптом — LazyInitializationException.
  • @Transactional нужен на уровне сервиса/метода, где происходит чтение и использование lazy-данных.
  • @Lazy и @Transactional решают разные задачи и не взаимозаменяемы.