간단한 프로젝트를 진행하던 와중 아래의 에러가 발생했다.
Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: failed to lazily initialize a collection of role: com.egemony.back.board.domain.Board.boardReply: could not initialize proxy - no Session]
Entity를 Dto로 변환하는 과정이다.
(findAllBoards 함수 > listOf 함수 > of 함수)
package com.egemony.back.board.service.impl;
import com.egemony.back.board.domain.Board;
import com.egemony.back.board.domain.BoardRepository;
import com.egemony.back.board.dto.request.BoardAddRequest;
import com.egemony.back.board.dto.response.BoardResponse;
import com.egemony.back.board.service.BoardService;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@RequiredArgsConstructor
@Transactional
public class BoardServiceImpl implements BoardService {
private final BoardRepository boardRepository;
@Override
public List<BoardResponse> findAllBoards() {
List<Board> boards = boardRepository.findAll();
return BoardResponse.listOf(boards);
}
}
package com.egemony.back.board.domain;
import com.egemony.back.boardreply.domain.BoardReply;
import com.egemony.back.common.domain.BaseTimeEntity;
import jakarta.persistence.*;
import lombok.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "board")
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public class Board extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long boardId;
@OneToMany(mappedBy = "board", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<BoardReply> boardReply = new ArrayList<>();
private String content;
private String ip;
private Integer replyCount;
}
package com.egemony.back.board.dto.response;
import com.egemony.back.board.domain.Board;
import com.egemony.back.boardreply.domain.BoardReply;
import lombok.Builder;
import lombok.Getter;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Getter
@Builder
public class BoardResponse {
private Long boardId;
private List<BoardReply> boardReply = new ArrayList<>();
private String content;
private String ip;
private LocalDateTime createAt;
private Integer replyCount;
public static BoardResponse of(Board board) {
return BoardResponse.builder()
.boardId(board.getBoardId())
.boardReply(board.getBoardReply())
.content(board.getContent())
.ip(board.getIp())
.createAt(board.getCreateAt())
.replyCount(board.getReplyCount())
.build();
}
public static List<BoardResponse> listOf(List<Board> boards) {
List<BoardResponse> boardResponses = new ArrayList<>();
for (Board board : boards) {
boardResponses.add(of(board));
}
return boardResponses;
}
}
boardReply 객체가 초기화되지 않은 상태로 JSON으로 변환하려고 하기 때문에 에러가 발생하고 있다.
해결 방법으로는 트랜잭션 어노테이션 내에서 초기화를 해주면 된다고 한다.
@Override
public List<BoardResponse> findAllBoards() {
List<Board> boards = boardRepository.findAll();
// 각 Board의 boardReply 필드 강제 초기화
boards.forEach(board -> board.getBoardReply().size());
return BoardResponse.listOf(boards);
}