|
안녕하세요, 코딩하는곰입니다. 😊
JPA를 사용하시는 개발자분들 중 LazyInitializationException으로 머리를 싸매신 경험이 한 번쯤은 있으시죠? 이 예외는 JPA의 지연 로딩(Lazy Loading) 메커니즘에서 빈번히 발생하는 문제로, 오늘은 이 에러의 근본적인 원인과 5가지 실전 해결 방법을 상세히 설명드리겠습니다.
특히 트랜잭션 범위와 영속성 컨텍스트 생명주기 관점에서 풀어보는 이 내용은 여러분의 JPA 이해도를 한 단계 업그레이드시켜줄 것입니다!
|
LazyInitializationException은 영속성 컨텍스트가 종료된 후 지연 로딩된 객체에 접근할 때 발생합니다. Hibernate는 지연 로딩을 구현하기 위해 프록시 객체를 사용하는데, 이 프록시가 초기화되려면 영속성 컨텍스트가 활성 상태여야 합니다.
@Transactionalpublic Order getOrder(Long id) {return orderRepository.findById(id).orElseThrow(); // Order 엔티티 반환 (컬렉션은 LAZY)}// 컨트롤러public void processOrder() {Order order = orderService.getOrder(1L);order.getItems().size(); // 여기서 예외 발생!}
order.getItems() 호출 graph LRA[프록시 객체] -->|초기화 요청| B[영속성 컨텍스트]B -->|DB 조회| C[실제 엔티티]B -->|없을 경우| D[LazyInitializationException]
|
Spring Boot에서는 spring.jpa.open-in-view=true(기본값)로 OSIV를 활성화합니다.
spring:jpa:open-in-view: true # 요청 시작부터 뷰 렌더링 완료까지 영속성 컨텍스트 유지
@Query("SELECT o FROM Order o JOIN FETCH o.items WHERE o.id = :id")Optional<Order> findByIdWithItems(@Param("id") Long id);
DISTINCT 추가 권장 @Transactionalpublic Order getInitializedOrder(Long id) {Order order = orderRepository.findById(id).orElseThrow();Hibernate.initialize(order.getItems()); // 명시적 초기화return order;}
영문, 숫자, 특수문자가 조합된 강력한 비밀번호가 필요하다면 무설치 비밀번호 생성기가 편리합니다.
|
@EntityGraph(attributePaths = {"items"})@Query("SELECT o FROM Order o WHERE o.id = :id")Optional<Order> findByIdWithEntityGraph(@Param("id") Long id);
@EntityGraph(type = EntityGraph.EntityGraphType.FETCH, attributePaths = {Order_.ITEMS}) @Transactional(readOnly = true)public OrderDto getOrderDto(Long id) {return orderRepository.findById(id).map(order -> new OrderDto(order.getId(),order.getItems().stream().map(ItemDto::new).toList())).orElseThrow();}
spring.jpa.properties.hibernate.default_batch_fetch_size=100
치매 예방과 인지 기능 향상을 위한 앱을 찾고 있다면, AI 기반 힌트와 함께하는 스도쿠 저니를 추천합니다.
|
지금까지 JPA LazyInitializationException의 다양한 해결 방법을 살펴보았습니다. 🎯
각 기법은 트레이드오프가 존재하므로, 애플리케이션의 특성에 맞게 선택해야 합니다.
📌 영양제 선택이 어려울 때 참고하면 좋은, 고려홍삼콜라겐 프리미엄를 참고해보세요.
