(error) could not initialize proxy ~~ - no Session

전성영·2022년 6월 29일
0

Error

목록 보기
14/16

즉시로딩은 성능에 좋지 않아 디폴트값이 Eager인 @OneToOne을 지연로딩으로 해줬다.

지연로딩으로 한 가장 큰 이유는 불필요한 쿼리를 줄이고 성능을 향상시키기 위해 설정을 해주었다.

그랬더니 갑자기 난 에러!!

지연 로딩을 하려는데 이미 세션이 사라져서 지연 로딩을 못할 때 발생하는 에러이다.
즉 영속성을 잃어버린 준영속 상태의 엔티티에 지연로딩을 시도했기 때문에 발생한 에러이다.

.getUser()는 UserDetailsServiceImpl에서 조회된 유저 정보가 담긴다. 서비스 로직이 아닌 UserDetailsServiceImpl에서 트랜잭션이 끝나서 영속성을 잃어버렸고, 그런 과정에서 lazy loading 방식의 추가적인 쿼리를 견디지 못한 것이다.

해결방법

  • 지연로딩을 즉시로딩으로 바꾸기

  • @Transactional을 붙여주거나.(근데 얘는 이미 붙여줌)

  • property에 밑 코드를 추가

<property name="hibernate.enable_lazy_load_no_trans" value="true"/>

얘는 N+1 문제가 나온다고 한다.

여기서 N+1 이란?
조회된 데이터 갯수(n) 만큼 연관관계의 조회 쿼리가 추가로 발생하여 데이터를 읽어오게 되는 것이다.


이렇게 수많은 해결책들이 나왔다. 하지만 두 가지 방법으로 풀 수 있을 거 같다.

해결방법_01
@EntityGraph 사용이다.
@EntityGraph 는 fetch조인을 어노테이션으로 사용할 수 있게 해주는 귀하신 분이다.

@Override //기본 적으로 findAll 을 제공하기 때문에 Override 하여 재정의 후 사용 
@EntityGraph(attributePaths = {"character"}) // DataJpa 에서 fetch 조인을 하기 위한 설정
List<Member> findAll();

이런식으로 사용하면 된다.

해결방법_02

Member m = userDetails.getMember();					(전)

			ㅣ
			ㅣ
			ㅣ	

Long memberId = userDetails.getMember().getId();
Member m = memberRepository.findById(memberId).orElseThrow(		(후)
            () -> new IllegalArgumentException("X")
    );
profile
Slow and Steady

0개의 댓글