컨텐츠 상세페이지에 대한 데이터를 dto 로 만들어 넘기는 api 를 만들어야한다.
{
"status": "200",
"msg": "ok",
"data":
{
"id": 1,
"thumbnail" : "thumbnail.png",
"tag1" : "시장정보",
"tag2" : "쉽게읽혀요",
"title" : "컨텐츠제목",
"createdAt" : "2023-05-05",
"pbId" : 1,
"name" : "김피비",
"profile" : "person.png",
"speciality1": "US_STOCK", // 전문 분야
"speciality2": null, // 2번이 없으면 null
"career" : 3,
"content" : "본문~~~"
"reply" : [
{ "id" : 1,
"name" : "투자자1",
"profile" : "person.png",
"replyContent" : "댓글내용1",
"createdAt" : 2023-05-05,
"parentId" : null
},
{ "id" : 2,
"name" : "투자자2",
"profile" : "person.png",
"replyContent" : "댓글내용2",
"createdAt" : 2023-05-05,
"parentId" : 1
}
]
}
}
위처럼 응답하기 위해 dto 만들었고, 해당 데이터들을 받기 위한 Spring data JPA 쿼리문을 만들어야하는데, spring data jpa 에서는 List<> 타입을 parameter 로 받지 못한다고 한다.
따라서 dto 의 매개변수에서 List<'Reply> 를 빼고, Reply 들은 다른 쿼리 메서드를 통해 가져온 후 setter 이용해 dto 에 추가하는 방식으로 repository 메서드를 구성했다.
그런데 서버 실행 후 요청하니, 다음과 같은 오류가 발생했다.
{
"status": 200,
"msg": "ok",
"data": {
"id": 1,
"thumbnail": "thumbnail.png",
"tag1": "시장정보",
"tag2": "쉽게읽혀요",
"createdAt": "2023-06-07T17:18:27.905958",
"pbId": 1,
"name": "김pb",
"profile": "profile.png",
"speciality1": "BOND",
"speciality2": null,
"career": 10,
"content": "content 입니다",
"reply": [
{
"id": 1,
"board": {
"id": 1,
"pb": {
"id": 1,
"branch": {
"id": 1
}
}
}
}
]
}
}{
"status": 500,
"msg": "unknownServerError",
"data": "Could not write JSON: could not initialize proxy [kr.co.moneybridge.model.pb.Branch#1] - no Session; nested exception is com.fasterxml.jackson.databind.JsonMappingException: could not initialize proxy [kr.co.moneybridge.model.pb.Branch#1] - no Session (through reference chain: kr.co.moneybridge.dto.ResponseDTO[\"data\"]->kr.co.moneybridge.dto.board.BoardResponse$BoardDetailDTO[\"reply\"]->java.util.ArrayList[0]->kr.co.moneybridge.model.board.Reply[\"board\"]->kr.co.moneybridge.model.board.Board[\"pb\"]->kr.co.moneybridge.model.pb.PB$HibernateProxy$5lPglno6[\"branch\"]->kr.co.moneybridge.model.pb.Branch$HibernateProxy$NYYWpsqe[\"company\"])"
}
알아보니, Reply 객체들이 Lazy loading 으로 가져와야하는 엔티티들과 연관관계가 맺어있는데, 조회시 이미 hibernate 세션이 닫혀있어서 발생하는 문제였다.
이를 해결하기 위해, dto 에서 List<'Reply> 가 아닌, List<'ReplyDto>로 포장했고, repository 에서 한번에 ReplyDto List 를 가져온 후 setter 통해 responseDto 에 추가해주었다.
@Query("SELECT NEW kr.co.moneybridge.dto.board.BoardResponse$BoardDetailDTO(b, pb) " +
"FROM Board b " +
"JOIN PB pb ON b.pb.id = pb.id " +
"WHERE b.id = :boardId AND b.status = :status")
BoardResponse.BoardDetailDTO findBoardWithPBReply(@Param("boardId") Long boardId, @Param("status") BoardStatus status);
@Query("SELECT NEW kr.co.moneybridge.dto.board.BoardResponse$ReplyOutDTO(r, u) " +
"FROM Reply r " +
"INNER JOIN User u ON r.user.id = u.id " +
"WHERE r.board.id = :boardId AND r.status = :status")
List<BoardResponse.ReplyOutDTO> findRepliesByBoardId(@Param("boardId") Long boardId, @Param("status") Boolean status);