반응형

원인

Member와 Message가 연관관계를 맺고 있고 1:N 관계를 가지고 있다.
Message 엔티티에서 Member Fetch 전략을 Lazy로 설정해준 상태이다.

오류 예시

// 메시지 제목, 내용, 작성자 이름, 받는 사람 이름 등의 정보가 들어있는 MessageResponseDTO로 변환하여 리소스를 반환하는 API

@GetMapping("/message/{message_id}")
public Result readMessage(@PathVariable Long message_id){
    Message msg = messageService.findB yId(message_id);
    MessageResponseDto messageResponseDto = MessageResponseDto.covertMessageDto(msg);
    return responseService.getSingleResult(messageResponseDto);
}

오류발생

  • Message를 단건조회하면 Message와 Lazy Loding으로 연관된 Member는 바로 초기화 되지 않고 필요할 때 정보가 채워지는 프록시 객체로 채워진다.

Message = Message 필드 + Member Proxy 객체

  • Member의 값을 써서 DTO를 채워야하는데 Member의 값이 초기화 되지 않은 상태라서 DTO를 만들 수 없음.

Lazy Loding방식이니 변환하면서 데이터를 사용할 때 쿼리를 날려 Proxy 객체를 채우지 못함.
-> Service에서 트랜잭션이 일어나도록 설정을 하였음. JPA 영속성 컨텍스트는 보통 트랜잭션과 생명주기를 같이한다. 그 말은 Service -> Controller로 나오면서 영속성 상태가 끝난다는 뜻이다. 더이상 영속성 컨텍스트에서 관리하지 않고 Member에 필요한 값이 있을때 쿼리를 날려 Proxy 객체를 채우지 않는다는 뜻이다.

해결방법

  1. Message -> DTO 변환을 컨트롤러 단에서 서비스 단으로 변경
@GetMapping("/message/{message_id}")
public Result readMessage(@PathVariable Long message_id){
    MessageResponseDto messageResponseDto = messageService.findByMessageId(message_id);
    return responseService.getSingleResult(messageResponseDto);
}
  1. Message에 있는 Member를 즉시로딩(Eager)로 변경한다.
  • 추천하지 않음.
반응형

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

QueryDsl이란? 왜 사용하는가?  (0) 2023.12.15
JPA-OSIV(Open Session In View)  (0) 2023.10.14
[JPA] GeneratedValue  (0) 2023.09.10
[JPA] Auditing - 공통 도메인 작업  (0) 2023.09.10
[JPA] @MappedSuperclass  (0) 2023.09.10

+ Recent posts