상세 컨텐츠

본문 제목

[JPA] LazyInitializationException

개발

by GoblinMode 2024. 2. 9. 12:03

본문

728x90
반응형

JPA 사용하자마자 만난 Exception

 

LazyInitializationException

 

.무슨 에러인지 왜 나는지도 하나도 모르는 상태에서 만난 Exception...

 

찾아보니 유명한 Exception입니다. JPA를 사용하면 만날수밖에없는 Exception 이라고 합니다.

 

이 Exception은 DB Session 문제입니다. 정확한 원인을 이해하려면 

 

JPA에 트랜잭션(Transaction)과, 생명주기를 이해야 해야 하는데 당장 그런부분 까지 이해하기에는

 

시간이 없습니다.

 

간단한 해결 방법

application.yaml, xml 파일에 옵션 수정

spring.jpa.open-in-view = false(기본값) > true(수정값)

 

spring.jpa.properties.hibernate.enable_lazy_load_no_trans = false(기본값) >  true(수정값)

 

해당 방법들이 제일 쉬운방법이나, 성능 문제가 발생할수있어, 급하게 프로젝트를 진행해야 할때 사용하시고,

 

해결방법을 찾아보시기를 바랍니다.

 

 

맞는 해결 방법 찾기

1. FetchType을 EAGER로 변경 관련된 객체를 즉시 로딩하도록 FetchType을 EAGER로 변경할 수 있습니다. 
이렇게하면 객체를 가져올 때 필요한 모든 연관 객체도 함께 로딩됩니다. 
하지만 모든 상황에서 EAGER 로딩을 사용하는 것은 성능에 영향을 줄 수 있으므로 신중하게 고려해야 합니다.

 

2. DTO를 사용하여 필요한 데이터만 조회 LazyInitializationException이 발생하는 경우, 
엔티티 대신 DTO(Data Transfer Object)를 사용하여 필요한 데이터만 조회하는 방법도 있습니다. 
DTO를 사용하면 연관된 객체를 직접 로딩하지 않고 필요한 데이터만 조회하여 예외를 피할 수 있습니다.

 

DTO를 사용한 방법이 제일 괜찮아보여, 사용 예제를 봐보자

 

public class UserDTO {
    private Long id;
    private String name;
    private List<String> orderProducts;
    
    public UserDTO(Long id, String name, List<String> orderProducts) {
        this.id = id;
        this.name = name;
        this.orderProducts = orderProducts;
    }
}

UserDTO 클래스는 User 엔티티의 필요한 데이터와 Order의 product 정보를 저장하는 orderProducts 필드를 가지고 있습니다.
이제 UserRepository나 UserService에서 UserDTO를 사용하여 필요한 데이터만 조회하는 예제를 보여드리겠습니다.

 

@Repository
public class UserRepository {
    @PersistenceContext
    private EntityManager entityManager;
    
    public UserDTO findUserWithOrders(Long userId) {
        User user = entityManager.find(User.class, userId);
        
        List<String> orderProducts = user.getOrders().stream()
                .map(Order::getProduct)
                .collect(Collectors.toList());
        
        return new UserDTO(user.getId(), user.getName(), orderProducts);
    }
}

 

위의 UserRepository 클래스에서는 EntityManager를 사용하여 User를 조회하고,  User의 orders 컬렉션을 스트림으로 변환하여 Order의 product 정보만 추출하여 orderProducts 리스트에 저장합니다. 그리고 UserDTO 객체에 필요한 데이터를 담아 반환합니다. 이렇게 DTO를 사용하여 필요한 데이터만 조회하면 LazyInitializationException을 피할 수 있습니다. 필요한 데이터만 조회하여 성능을 최적화할 수 있습니다. 위의 예제는 간단한 예시일 뿐이며, 실제 프로젝트에서는 더 복잡한 구조와 로직이 있을 수 있습니다. 상황에 맞게 DTO를 활용하여 LazyInitializationException을 피하고,  필요한 데이터를 효율적으로 조회해보시기 바랍니다.

728x90
반응형

'개발' 카테고리의 다른 글

[Java] 객체지향 언어란?  (0) 2024.03.19
[JPA] 쓸려면 알아야할 기본 용어  (0) 2024.02.14
[Java] 스레드(thread)란?  (2) 2024.02.08
[Java] 메소드란?  (0) 2024.02.07
[OpenShift]오픈시프트 관련 내용  (0) 2024.02.01

관련글 더보기