JPA Could not write JSON: failed to lazily initialize a collection of role 에러 해결

인지용·2023년 11월 28일
1

간단한 프로젝트를 진행하던 와중 아래의 에러가 발생했다.

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);
    }
profile
한-줄

0개의 댓글

관련 채용 정보