원인
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 객체를 채우지 않는다는 뜻이다.
해결방법
- Message -> DTO 변환을 컨트롤러 단에서 서비스 단으로 변경
@GetMapping("/message/{message_id}")
public Result readMessage(@PathVariable Long message_id){
MessageResponseDto messageResponseDto = messageService.findByMessageId(message_id);
return responseService.getSingleResult(messageResponseDto);
}
- 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 |